diff --git a/.editorconfig b/.editorconfig index e43c0e094..c60879fb3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -342,7 +342,7 @@ ij_editorconfig_space_before_colon = false ij_editorconfig_space_before_comma = false ij_editorconfig_spaces_around_assignment_operators = true -[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.pom, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul}] +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] ij_xml_align_attributes = true ij_xml_align_text = false ij_xml_attribute_wrap = normal @@ -360,7 +360,7 @@ ij_xml_space_around_equals_in_attribute = false ij_xml_space_inside_empty_tag = false ij_xml_text_wrap = normal -[{*.ats, *.ts}] +[{*.ats,*.ts}] ij_continuation_indent_size = 4 ij_typescript_align_imports = false ij_typescript_align_multiline_array_initializer_expression = false @@ -528,7 +528,7 @@ ij_typescript_while_brace_force = never ij_typescript_while_on_new_line = false ij_typescript_wrap_comments = false -[{*.bash, *.sh, *.zsh}] +[{*.bash,*.sh,*.zsh}] indent_size = 2 tab_width = 2 ij_shell_binary_ops_start_line = false @@ -537,7 +537,7 @@ ij_shell_minify_program = false ij_shell_redirect_followed_by_space = false ij_shell_switch_cases_indented = false -[{*.cjs, *.js}] +[{*.cjs,*.js}] ij_continuation_indent_size = 4 ij_javascript_align_imports = false ij_javascript_align_multiline_array_initializer_expression = false @@ -702,10 +702,10 @@ ij_javascript_while_brace_force = never ij_javascript_while_on_new_line = false ij_javascript_wrap_comments = false -[{*.ft, *.vm, *.vsl}] +[{*.ft,*.vm,*.vsl}] ij_vtl_keep_indents_on_empty_lines = false -[{*.gant, *.gradle, *.groovy, *.gy}] +[{*.gant,*.gradle,*.groovy,*.gy}] ij_groovy_align_group_field_declarations = false ij_groovy_align_multiline_array_initializer_expression = false ij_groovy_align_multiline_assignment = false @@ -884,7 +884,7 @@ ij_groovy_while_brace_force = never ij_groovy_while_on_new_line = false ij_groovy_wrap_long_lines = false -[{*.gradle.kts, *.kt, *.kts, *.main.kts}] +[{*.gradle.kts,*.kt,*.kts,*.main.kts}] ij_kotlin_align_in_columns_case_branch = false ij_kotlin_align_multiline_binary_operation = false ij_kotlin_align_multiline_extends_list = false @@ -963,7 +963,7 @@ ij_kotlin_wrap_elvis_expressions = 1 ij_kotlin_wrap_expression_body_functions = 0 ij_kotlin_wrap_first_method_in_call_chain = false -[{*.har, *.jsb2, *.jsb3, *.json, .babelrc, .eslintrc, .stylelintrc, bowerrc, jest.config, mcmod.info}] +[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config,mcmod.info}] indent_size = 2 ij_json_keep_blank_lines_in_code = 0 ij_json_keep_indents_on_empty_lines = false @@ -976,7 +976,7 @@ ij_json_spaces_within_braces = false ij_json_spaces_within_brackets = false ij_json_wrap_long_lines = false -[{*.htm, *.html, *.sht, *.shtm, *.shtml}] +[{*.htm,*.html,*.sht,*.shtm,*.shtml}] ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 ij_html_align_attributes = true ij_html_align_text = false @@ -1004,7 +1004,7 @@ ij_html_space_inside_empty_tag = false ij_html_text_wrap = normal ij_html_uniform_ident = false -[{*.yaml, *.yml}] +[{*.yaml,*.yml}] indent_size = 2 ij_yaml_keep_indents_on_empty_lines = false ij_yaml_keep_line_breaks = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 8a134b81e..e5da90873 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -27,11 +27,11 @@ body: description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. multiple: false options: - - '1.20.1' - - '1.20' - - '1.19.4' - - '1.18.2' - - '1.17.1' + - '1.21.3' + - '1.21.1' + - '1.20.6' + - '1.20.4' + - '1.20.2' validations: required: true diff --git a/.github/renovate.json b/.github/renovate.json index d0e59d791..6b7783c42 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,18 +1,19 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:base", - ":semanticCommitsDisabled" + "$schema" : "https://docs.renovatebot.com/renovate-schema.json", + "extends" : [ + "config:recommended", + ":semanticCommitsDisabled", + "schedule:earlyMondays" ], - "automerge": true, - "ignoreDeps": [ - "guava", + "automerge" : true, + "ignoreDeps" : [ + "guava", "com.google.guava:guava", "rhino-runtime", "org.antlr", "antlr4-runtime", "fastutil", - "it.unimi.dsi:fastutil", + "it.unimi.dsi:fastutil", "auto-value-annotations", "auto-value", "com.google.code.gson:gson", @@ -29,7 +30,34 @@ "org.spongepowered:spongeapi", "org.yaml:snakeyaml" ], - "labels": ["Renovate"], - "rebaseWhen": "conflicted", - "schedule": ["on the first day of the month"] + "labels" : [ + "Renovate" + ], + "rebaseWhen" : "conflicted", + "customManagers" : [ + { + "customType" : "regex", + "datasourceTemplate" : "custom.paperweight-userdev", + "fileMatch" : "^worldedit-bukkit\\/adapters\\/adapter-\\d+_\\d+(_\\d+)?\\/build\\.gradle\\.kts$", + "matchStrings" : [ + "url=(?.*)\\s", + "paperDevBundle\\(\"(?.*?)\"\\)\\s" + ], + "matchStringsStrategy": "combination", + "depNameTemplate" : "paperweight-userdev", + "extractVersionTemplate" : "(?\\d+\\.\\d+\\.?\\d*-R0\\.1-\\d+\\.\\d+-\\d+)" + } + ], + "customDatasources" : { + "paperweight-userdev": { + "defaultRegistryUrlTemplate": "", + "format": "html" + } + }, + "packageRules" : [ + { + "matchDatasources" : ["custom.paperweight-userdev"], + "versioning": "regex:^(?\\d+)\\.(?\\d+)\\.(?\\d+)?-R0\\.1-\\d+\\d+\\.\\d+-(?\\d+)$" + } + ] } diff --git a/.github/workflows/announce-release-on-discord.yml b/.github/workflows/announce-release-on-discord.yml index 77fa89732..61038e9a3 100644 --- a/.github/workflows/announce-release-on-discord.yml +++ b/.github/workflows/announce-release-on-discord.yml @@ -24,5 +24,5 @@ jobs: "" "The download is available at:" "- Spigot: " - "- Modrinth: " + "- Modrinth: " "- CurseForge: " diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 11f0d1d5d..8766c697b 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -9,19 +9,19 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v4 - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Build on ${{ matrix.os }} run: ./gradlew build -s - name: Archive artifacts uses: actions/upload-artifact@v3 with: name: FastAsyncWorldEdit-SNAPSHOT - path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar + path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-*.jar diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65555631f..a24529c9e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,15 +9,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v4 - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Clean Build run: ./gradlew clean build --no-daemon - name: Determine release status @@ -70,9 +70,9 @@ jobs: uses: actions/upload-artifact@v3 with: name: FastAsyncWorldEdit-Bukkit-SNAPSHOT - path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar + path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-*.jar - name: Publish to Modrinth if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} - run: ./gradlew modrinth + run: ./gradlew publishMods env: MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f4287607f..0cd6f4443 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,18 +19,18 @@ jobs: language: ['java'] steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/label-merge-conflicts.yaml b/.github/workflows/label-merge-conflicts.yaml new file mode 100644 index 000000000..8a2c30125 --- /dev/null +++ b/.github/workflows/label-merge-conflicts.yaml @@ -0,0 +1,23 @@ +name: "Label conflicting PRs" +on: + push: + pull_request_target: + types: [ synchronize ] + pull_request: + types: [ synchronize ] + +permissions: + pull-requests: write + +jobs: + main: + if: github.event.pull_request.user.login != 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Label conflicting PRs + uses: eps1lon/actions-label-merge-conflict@v3.0.2 + with: + dirtyLabel: "unresolved-merge-conflict" + repoToken: "${{ secrets.GITHUB_TOKEN }}" + commentOnDirty: "Please take a moment and address the merge conflicts of your pull request. Thanks!" + continueOnMissingPermissions: true diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 90248b436..131fb810e 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -12,6 +12,6 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/upload-release-assets.yml b/.github/workflows/upload-release-assets.yml index e93fc35c5..ea012486c 100644 --- a/.github/workflows/upload-release-assets.yml +++ b/.github/workflows/upload-release-assets.yml @@ -7,20 +7,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v4 - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Clean Build run: ./gradlew clean build --no-daemon - name: Upload Release Assets - uses: AButler/upload-release-assets@v2.0 + uses: AButler/upload-release-assets@v3.0 with: - files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar' + files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-*.jar' repo-token: ${{ secrets.GITHUB_TOKEN }} release-tag: ${{ github.event.release.tag_name }} diff --git a/COMPILING.adoc b/COMPILING.adoc index 87b21b685..bdd30ba62 100644 --- a/COMPILING.adoc +++ b/COMPILING.adoc @@ -3,12 +3,12 @@ = Compiling -You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed, +You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 21 installed. Gradle will download JDK 21 specifically if needed, but it needs some version of Java to bootstrap from. -Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 17. +Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 21. -You can get the JDK 17 link:https://adoptium.net/[here] from Adoptium. +You can get the JDK 21 link:https://adoptium.net/[here] from Adoptium. The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules: diff --git a/Jenkinsfile b/Jenkinsfile index 61000e9fb..94db4eda2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { stage('Build') { steps { withEnv([ - "PATH+JAVA=${tool 'Temurin-17.0.7_7'}/bin" + "PATH+JAVA=${tool 'Temurin-21.0.3_9'}/bin" ]) { sh './gradlew clean build' } diff --git a/build.gradle.kts b/build.gradle.kts index 5d74be915..5b5f3a42b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,8 +6,8 @@ import java.time.format.DateTimeFormatter import xyz.jpenilla.runpaper.task.RunServer plugins { - id("io.github.gradle-nexus.publish-plugin") version "1.3.0" - id("xyz.jpenilla.run-paper") version "2.1.0" + id("io.github.gradle-nexus.publish-plugin") version "2.0.0" + id("xyz.jpenilla.run-paper") version "2.3.1" } if (!File("$rootDir/.git").exists()) { @@ -34,7 +34,7 @@ logger.lifecycle(""" ******************************************* """) -var rootVersion by extra("2.7.1") +var rootVersion by extra("2.12.3") var snapshot by extra("SNAPSHOT") var revision: String by extra("") var buildNumber by extra("") @@ -83,7 +83,7 @@ allprojects { } applyCommonConfiguration() -val supportedVersions = listOf("1.16.5", "1.17", "1.17.1", "1.18.2", "1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1") +val supportedVersions = listOf("1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.3") tasks { supportedVersions.forEach { @@ -91,13 +91,13 @@ tasks { minecraftVersion(it) pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) - jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true") + jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true", "--add-modules=jdk.incubator.vector") group = "run paper" runDirectory.set(file("run-$it")) } } runServer { - minecraftVersion("1.20.1") + minecraftVersion("1.21.3") pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index de4d0df68..a7b6d53d7 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -22,13 +22,25 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) - implementation("org.ajoberstar.grgit:grgit-gradle:5.2.0") - implementation("com.github.johnrengelman:shadow:8.1.1") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.5") + implementation("org.ajoberstar.grgit:grgit-gradle:5.3.0") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.5") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.5") + constraints { + val asmVersion = "[9.7,)" + implementation("org.ow2.asm:asm:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.ow2.asm:asm-commons:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.vafer:jdependency:[2.10,)") { + because("Need Java 21 support in shadow") + } + } } kotlin { jvmToolchain { - (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17)) + (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(21)) } } diff --git a/buildSrc/src/main/kotlin/AdapterConfig.kt b/buildSrc/src/main/kotlin/AdapterConfig.kt index 60f9a5733..1d141621b 100644 --- a/buildSrc/src/main/kotlin/AdapterConfig.kt +++ b/buildSrc/src/main/kotlin/AdapterConfig.kt @@ -20,4 +20,8 @@ fun Project.applyPaperweightAdapterConfiguration() { tasks.named("assemble") { dependsOn("reobfJar") } + + tasks.named("javadoc") { + enabled = false + } } diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt index 6a6d552aa..e8fd3db87 100644 --- a/buildSrc/src/main/kotlin/CommonConfig.kt +++ b/buildSrc/src/main/kotlin/CommonConfig.kt @@ -33,7 +33,7 @@ fun Project.applyCommonConfiguration() { plugins.withId("java") { the().toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(21)) } } diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 549a26037..0b90d1e06 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -21,17 +21,18 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean .matching { it.name == "compileJava" || it.name == "compileTestJava" } .configureEach { val disabledLint = listOf( - "processing", "path", "fallthrough", "serial" + "processing", "path", "fallthrough", "serial", "overloads", "this-escape", ) - options.release.set(17) + options.release.set(21) options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) options.isDeprecation = true options.encoding = "UTF-8" options.compilerArgs.add("-parameters") + options.compilerArgs.add("--add-modules=jdk.incubator.vector") } configurations.all { - attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } tasks.withType().configureEach { @@ -40,30 +41,30 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean dependencies { "compileOnly"("com.google.code.findbugs:jsr305:3.0.2") - "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.10.0") - "testImplementation"("org.junit.jupiter:junit-jupiter-params:5.10.0") - "testImplementation"("org.mockito:mockito-core:5.4.0") - "testImplementation"("org.mockito:mockito-junit-jupiter:5.4.0") - "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.10.0") + "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.11.1") + "testImplementation"("org.junit.jupiter:junit-jupiter-params:5.11.1") + "testImplementation"("org.mockito:mockito-core:5.14.0") + "testImplementation"("org.mockito:mockito-junit-jupiter:5.14.0") + "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.11.1") } // Java 8 turns on doclint which we fail tasks.withType().configureEach { (options as StandardJavadocDocletOptions).apply { addStringOption("Xdoclint:none", "-quiet") + addStringOption("-add-modules", "jdk.incubator.vector") tags( "apiNote:a:API Note:", "implSpec:a:Implementation Requirements:", "implNote:a:Implementation Note:" ) options.encoding = "UTF-8" + links( "https://jd.advntr.dev/api/latest/", - "https://logging.apache.org/log4j/2.x/log4j-api/apidocs/", + "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://www.antlr.org/api/Java/", - "https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/", - "https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/", - "https://jd.papermc.io/paper/1.20/", + "https://jd.papermc.io/paper/1.21.1/", "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" ) docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 4fd69cb65..0599a8567 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -29,7 +29,7 @@ fun Project.applyLibrariesConfiguration() { applyCommonConfiguration() apply(plugin = "java-base") apply(plugin = "maven-publish") - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") apply(plugin = "signing") configurations { @@ -40,8 +40,7 @@ fun Project.applyLibrariesConfiguration() { val relocations = mapOf( "net.kyori.text" to "com.sk89q.worldedit.util.formatting.text", - "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori", - "net.kyori.adventure.nbt" to "com.sk89q.worldedit.util.nbt" + "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori" ) @@ -53,9 +52,14 @@ fun Project.applyLibrariesConfiguration() { exclude(dependency("com.google.guava:guava")) exclude(dependency("com.google.code.gson:gson")) exclude(dependency("com.google.errorprone:error_prone_annotations")) + exclude(dependency("com.google.guava:failureaccess")) exclude(dependency("org.checkerframework:checker-qual")) + exclude(dependency("org.jetbrains:annotations")) exclude(dependency("org.apache.logging.log4j:log4j-api")) exclude(dependency("com.google.code.findbugs:jsr305")) + exclude { + it.moduleGroup == "org.jetbrains.kotlin" + } } relocations.forEach { (from, to) -> @@ -67,11 +71,19 @@ fun Project.applyLibrariesConfiguration() { .filterIsInstance() .map { it.copy() } .map { dependency -> - dependency.artifact { - name = dependency.name - type = artifactType - extension = "jar" - classifier = artifactType + val category = dependency.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE)?.name + if (category == Category.REGULAR_PLATFORM || category == Category.ENFORCED_PLATFORM) { + return@map dependency + } + try { + dependency.artifact { + name = dependency.name + type = artifactType + extension = "jar" + classifier = artifactType + } + } catch (e: Exception) { + throw RuntimeException("Failed to add artifact to dependency: $dependency", e) } dependency } @@ -85,6 +97,10 @@ fun Project.applyLibrariesConfiguration() { from({ altConfigFiles("sources") }) + + // Yeet module-info's + exclude("module-info.java") + relocations.forEach { (from, to) -> val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)") val textPattern = Regex.fromLiteral(from) @@ -122,7 +138,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } outgoing.artifact(tasks.named("jar")) } @@ -137,7 +153,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } outgoing.artifact(tasks.named("jar")) } @@ -241,8 +257,9 @@ fun Project.applyLibrariesConfiguration() { scm { url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") } issueManagement { diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt index 807ee9e8a..1b89a362e 100644 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ b/buildSrc/src/main/kotlin/PlatformConfig.kt @@ -12,6 +12,7 @@ import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.provideDelegate import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.the +import org.gradle.kotlin.dsl.withType import org.gradle.plugins.signing.SigningExtension fun Project.applyPlatformAndCoreConfiguration() { @@ -20,7 +21,7 @@ fun Project.applyPlatformAndCoreConfiguration() { apply(plugin = "eclipse") apply(plugin = "idea") apply(plugin = "maven-publish") - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") apply(plugin = "signing") applyCommonJavaConfiguration( @@ -87,23 +88,27 @@ fun Project.applyPlatformAndCoreConfiguration() { name.set("Alexander Brandes") email.set("contact(at)notmyfault.dev") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } developer { id.set("SirYwell") name.set("Hannes Greule") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } developer { id.set("dordsor21") name.set("dordsor21") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } } scm { url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") } issueManagement{ @@ -128,7 +133,8 @@ fun Project.applyPlatformAndCoreConfiguration() { } fun Project.applyShadowConfiguration() { - tasks.named("shadowJar") { + tasks.withType().configureEach { + relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") dependencies { include(project(":worldedit-libs:core")) include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2172a6189..4b2bea419 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # Minecraft expectations -paper = "1.20.1-R0.1-SNAPSHOT" +paper = "1.21-R0.1-SNAPSHOT" fastutil = "8.5.9" guava = "31.1-jre" log4j = "2.19.0" @@ -9,48 +9,49 @@ snakeyaml = "2.0" # Plugins dummypermscompat = "1.10" -worldguard-bukkit = "7.0.9" +worldguard-bukkit = "7.0.12" mapmanager = "1.8.0-SNAPSHOT" -griefprevention = "16.18.1" +griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.99.5.10" -plotsquared = "7.0.0-rc.4" +towny = "0.100.4.13" +plotsquared = "7.4.0" # Third party -bstats = "3.0.2" -sparsebitset = "1.2" +bstats = "3.1.0" +sparsebitset = "1.3" parallelgzip = "1.0.5" -adventure = "4.14.0" -adventure-bukkit = "4.3.0" -checkerqual = "3.37.0" +adventure = "4.17.0" +adventure-bukkit = "4.3.4" +checkerqual = "3.48.2" truezip = "6.8.4" -auto-value = "1.10.2" +auto-value = "1.11.0" findbugs = "3.0.2" -rhino-runtime = "1.7.14" +rhino-runtime = "1.7.15" zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs -antlr4 = "4.13.0" +antlr4 = "4.13.2" json-simple = "1.1.1" jlibnoise = "1.0.0" jchronic = "0.2.4a" lz4-java = "1.8.0" lz4-stream = "1.0.0" -commons-cli = "1.5.0" +commons-cli = "1.9.0" paperlib = "1.0.8" -paster = "1.1.5" +paster = "1.1.6" vault = "1.7.1" -serverlib = "2.3.1" +serverlib = "2.3.6" +linbus = "0.2.0" ## Internal text-adapter = "3.0.6" text = "3.0.4" -piston = "0.5.7" +piston = "0.5.10" # Tests -mockito = "5.4.0" +mockito = "5.14.2" # Gradle plugins pluginyml = "0.6.0" -minotaur = "2.8.3" +mod-publish-plugin = "0.8.1" [libraries] # Minecraft expectations @@ -78,7 +79,6 @@ bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } sparsebitset = { group = "com.zaxxer", name = "SparseBitSet", version.ref = "sparsebitset" } parallelgzip = { group = "org.anarres", name = "parallelgzip", version.ref = "parallelgzip" } -adventureNbt = { group = "net.kyori", name = "adventure-nbt", version.ref = "adventure" } truezip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" } autoValueAnnotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" } autoValue = { group = "com.google.auto.value", name = "auto-value", version.ref = "auto-value" } @@ -101,6 +101,11 @@ paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" } checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" } +linBus-bom = { group = "org.enginehub.lin-bus", name = "lin-bus-bom", version.ref = "linbus" } +linBus-common = { group = "org.enginehub.lin-bus", name = "lin-bus-common" } +linBus-stream = { group = "org.enginehub.lin-bus", name = "lin-bus-stream" } +linBus-tree = { group = "org.enginehub.lin-bus", name = "lin-bus-tree" } +linBus-format-snbt = { group = "org.enginehub.lin-bus.format", name = "lin-bus-format-snbt" } # Internal ## Text @@ -122,4 +127,4 @@ log4jCore = { group = "org.apache.logging.log4j", name = "log4j-core", version.r [plugins] pluginyml = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "pluginyml" } -minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" } +mod-publish-plugin = { id = "me.modmuss50.mod-publish-plugin", version.ref = "mod-publish-plugin" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4c..a4b76b953 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d5f..e2847c820 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca14..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..9b42019c7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle.kts b/settings.gradle.kts index 8e8ebe625..d724e7a4e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit" include("worldedit-libs") -listOf("legacy", "1_17_1", "1_18_2", "1_19", "1_19_3","1_19_4", "1_20").forEach { +listOf("1_20_2", "1_20_4", "1_20_5", "1_21", "1_21_3").forEach { include("worldedit-bukkit:adapters:adapter-$it") } diff --git a/steamwarci.yml b/steamwarci.yml index ff7ddde8c..612416b6b 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -1,9 +1,9 @@ build: - - "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew build" - - "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew --stop" + - "JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew build" + - "JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew --stop" artifacts: - "/binarys/FastAsyncWorldEdit-1.18.jar": "worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-2.7.1-SNAPSHOT.jar" + "/binarys/FastAsyncWorldEdit-1.21.jar": "worldedit-bukkit/build/libs/FastAsyncWorldEdit-Paper-2.12.3-SNAPSHOT.jar" release: - - "mvn deploy:deploy-file -DgroupId=de.steamwar -DartifactId=fastasyncworldedit -Dversion=1.18 -Dpackaging=jar -Dfile=/binarys/FastAsyncWorldEdit-1.18.jar -Durl=file:///var/www/html/maven/" + - "mvn deploy:deploy-file -DgroupId=de.steamwar -DartifactId=fastasyncworldedit -Dversion=1.21 -Dpackaging=jar -Dfile=/binarys/FastAsyncWorldEdit-1.21.jar -Durl=file:///var/www/html/maven/" diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_17_1/build.gradle.kts deleted file mode 100644 index 24c121c3f..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension - -applyPaperweightAdapterConfiguration() - -plugins { - java -} - -repositories { - mavenCentral() - gradlePluginPortal() -} - -java { - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) -} - -configurations.all { - attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) -} - - -dependencies { - the().paperDevBundle("1.17.1-R0.1-20220414.034903-210") - compileOnly(libs.paperlib) -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java deleted file mode 100644 index f369b8458..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe; - -import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.platform.Watchdog; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; -import com.sk89q.worldedit.world.DataFixer; -import com.sk89q.worldedit.world.RegenOptions; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.item.ItemType; -import net.minecraft.Util; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.StringRepresentable; -import net.minecraft.util.thread.BlockableEventLoop; -import net.minecraft.world.Clearable; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkBiomeContainer; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World.Environment; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_17_R1.CraftServer; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.generator.ChunkGenerator; -import org.spigotmc.SpigotConfig; -import org.spigotmc.WatchdogThread; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.OptionalLong; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -public final class PaperweightAdapter implements BukkitImplAdapter { - - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); - - private final Field worldsField; - private final Method getChunkFutureMainThreadMethod; - private final Field mainThreadProcessorField; - private final Watchdog watchdog; - - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ - - public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { - // A simple test - CraftServer.class.cast(Bukkit.getServer()); - - int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2730) { - throw new UnsupportedClassVersionError("Not 1.17.1!"); - } - - worldsField = CraftServer.class.getDeclaredField("worlds"); - worldsField.setAccessible(true); - - getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread", - int.class, int.class, ChunkStatus.class, boolean.class - ); - getChunkFutureMainThreadMethod.setAccessible(true); - - mainThreadProcessorField = ServerChunkCache.class.getDeclaredField( - Refraction.pickName("mainThreadProcessor", "h") - ); - mainThreadProcessorField.setAccessible(true); - - new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); - - Watchdog watchdog; - try { - Class.forName("org.spigotmc.WatchdogThread"); - watchdog = new SpigotWatchdog(); - } catch (ClassNotFoundException | NoSuchFieldException e) { - try { - watchdog = new MojangWatchdog(((CraftServer) Bukkit.getServer()).getServer()); - } catch (NoSuchFieldException ex) { - watchdog = null; - } - } - this.watchdog = watchdog; - - try { - Class.forName("org.spigotmc.SpigotConfig"); - SpigotConfig.config.set("world-settings.faweregentempworld.verbose", false); - } catch (ClassNotFoundException ignored) { - } - } - - @Override - public DataFixer getDataFixer() { - return PaperweightDataConverters.INSTANCE; - } - - /** - * Read the given NBT data into the given tile entity. - * - * @param tileEntity the tile entity - * @param tag the tag - */ - static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) { - tileEntity.load(tag); - tileEntity.setChanged(); - } - - /** - * Write the tile entity's NBT data to the given tag. - * - * @param tileEntity the tile entity - * @param tag the tag - */ - private static void readTileEntityIntoTag(BlockEntity tileEntity, net.minecraft.nbt.CompoundTag tag) { - tileEntity.save(tag); - } - - /** - * Get the ID string of the given entity. - * - * @param entity the entity - * @return the entity ID - */ - private static String getEntityId(Entity entity) { - return EntityType.getKey(entity.getType()).toString(); - } - - /** - * Create an entity using the given entity ID. - * - * @param id the entity ID - * @param world the world - * @return an entity or null - */ - @Nullable - private static Entity createEntityFromId(String id, net.minecraft.world.level.Level world) { - return EntityType.byString(id).map(t -> t.create(world)).orElse(null); - } - - /** - * Write the given NBT data into the given entity. - * - * @param entity the entity - * @param tag the tag - */ - private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { - entity.load(tag); - } - - /** - * Write the entity's NBT data to the given tag. - * - * @param entity the entity - * @param tag the tag - */ - private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) { - entity.save(tag); - } - - private static Block getBlockFromType(BlockType blockType) { - return Registry.BLOCK.get(ResourceLocation.tryParse(blockType.getId())); - } - - private static Item getItemFromType(ItemType itemType) { - return Registry.ITEM.get(ResourceLocation.tryParse(itemType.getId())); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockData data) { - net.minecraft.world.level.block.state.BlockState state = ((CraftBlockData) data).getState(); - int combinedId = Block.getId(state); - return combinedId == 0 && state.getBlock() != Blocks.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockState state) { - Block mcBlock = getBlockFromType(state.getBlockType()); - net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); - Map, Object> states = state.getStates(); - newState = applyProperties(mcBlock.getStateDefinition(), newState, states); - final int combinedId = Block.getId(newState); - return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); - } - - @Deprecated - @Override - public BlockState getBlock(Location location) { - Preconditions.checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final CraftBlockData blockData = chunk.getBlockState(blockPos).createCraftBlockData(); - BlockState state = BukkitAdapter.adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; - } - - @Override - public BaseBlock getFullBlock(Location location) { - BlockState state = getBlock(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - - // Read the NBT data - BlockEntity te = chunk.getBlockEntity(blockPos); - if (te != null) { - net.minecraft.nbt.CompoundTag tag = te.save(new net.minecraft.nbt.CompoundTag()); - //FAWE start - BinaryTag - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - //FAWE end - } - - return state.toBaseBlock(); - } - - @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); - } - - private static net.minecraft.core.Direction adapt(Direction face) { - switch (face) { - case NORTH: - return net.minecraft.core.Direction.NORTH; - case SOUTH: - return net.minecraft.core.Direction.SOUTH; - case WEST: - return net.minecraft.core.Direction.WEST; - case EAST: - return net.minecraft.core.Direction.EAST; - case DOWN: - return net.minecraft.core.Direction.DOWN; - case UP: - default: - return net.minecraft.core.Direction.UP; - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private net.minecraft.world.level.block.state.BlockState applyProperties( - StateDefinition stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states - ) { - for (Map.Entry, Object> state : states.entrySet()) { - net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); - Comparable value = (Comparable) state.getValue(); - // we may need to adapt this value, depending on the source prop - if (property instanceof DirectionProperty) { - Direction dir = (Direction) value; - value = adapt(dir); - } else if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - String enumName = (String) value; - value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); - } - - newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value - ); - } - return newState; - } - - @Override - public BaseEntity getEntity(org.bukkit.entity.Entity entity) { - checkNotNull(entity); - - CraftEntity craftEntity = ((CraftEntity) entity); - Entity mcEntity = craftEntity.getHandle(); - - String id = getEntityId(mcEntity); - - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, tag); - //FAWE start - BinaryTag - return new BaseEntity( - com.sk89q.worldedit.world.entity.EntityTypes.get(id), - LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)) - ); - //FAWE end - } - - @Nullable - @Override - public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) { - checkNotNull(location); - checkNotNull(state); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - ServerLevel worldServer = craftWorld.getHandle(); - - Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle()); - - if (createdEntity != null) { - CompoundTag nativeTag = state.getNbtData(); - if (nativeTag != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNative(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - readTagIntoEntity(tag, createdEntity); - } - - createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - - worldServer.addEntity(createdEntity, SpawnReason.CUSTOM); - return createdEntity.getBukkitEntity(); - } else { - return null; - } - } - - @Override - public Component getRichBlockName(BlockType blockType) { - return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); - } - - @Override - public Component getRichItemName(ItemType itemType) { - return TranslatableComponent.of(getItemFromType(itemType).getDescriptionId()); - } - - @Override - public Component getRichItemName(BaseItemStack itemStack) { - return TranslatableComponent.of(CraftItemStack.asNMSCopy(BukkitAdapter.adapt(itemStack)).getDescriptionId()); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); - - @SuppressWarnings({ "rawtypes" }) - @Override - public Map> getProperties(BlockType blockType) { - Map> properties = new TreeMap<>(); - Block block = getBlockFromType(blockType); - StateDefinition blockStateList = - block.getStateDefinition(); - for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { - Property property = PROPERTY_CACHE.getUnchecked(state); - properties.put(property.getName(), property); - } - return properties; - } - - @Override - public void sendFakeNBT(final Player player, final BlockVector3 pos, final CompoundBinaryTag nbtData) { - - } - - @Override - public void sendFakeOP(Player player) { - ((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 - )); - } - - @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { - ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); - return CraftItemStack.asCraftMirror(stack); - } - - @Override - public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { - final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbtData(((CompoundTag) toNative(nmsStack.getTag()))); - return weStack; - } - - private final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); - - @Override - public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { - CraftWorld craftWorld = (CraftWorld) world; - ServerLevel worldServer = craftWorld.getHandle(); - ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack - ? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); - stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); - - PaperweightFakePlayer fakePlayer; - try { - fakePlayer = fakePlayers.get(worldServer); - } catch (ExecutionException ignored) { - return false; - } - fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); - fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(), - (float) face.toVector().toYaw(), (float) face.toVector().toPitch() - ); - - final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos); - final net.minecraft.core.Direction enumFacing = adapt(face); - BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false); - UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace); - InteractionResult result = stack.placeItem(context, InteractionHand.MAIN_HAND); - if (result != InteractionResult.SUCCESS) { - if (worldServer - .getBlockState(blockPos) - .use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace) - .consumesAction()) { - result = InteractionResult.SUCCESS; - } else { - result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult(); - } - } - - return result == InteractionResult.SUCCESS; - } - - @Override - public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) { - int internalId = BlockStateIdAccess.getBlockStateId(blockState); - net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId); - return blockData.canSurvive( - ((CraftWorld) world).getHandle(), - new BlockPos(position.getX(), position.getY(), position.getZ()) - ); - } - - @Override - public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) { - try { - doRegen(bukkitWorld, region, extent, options); - } catch (Exception e) { - throw new IllegalStateException("Regen failed.", e); - } - - return true; - } - - private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception { - Environment env = bukkitWorld.getEnvironment(); - ChunkGenerator gen = bukkitWorld.getGenerator(); - - Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); - ResourceKey worldDimKey = getWorldDimKey(env); - try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { - ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); - PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() - .getWorldData().overworldData(); - WorldGenSettings originalOpts = levelProperties.worldGenSettings(); - - long seed = options.getSeed().orElse(originalWorld.getSeed()); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) - : originalOpts; - - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - levelProperties.settings.gameType(), - levelProperties.settings.hardcore(), - levelProperties.settings.difficulty(), - levelProperties.settings.allowCommands(), - levelProperties.settings.gameRules(), - levelProperties.settings.getDataPackConfig() - ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); - - ServerLevel freshWorld = new ServerLevel( - originalWorld.getServer(), - originalWorld.getServer().executor, - session, newWorldData, - originalWorld.dimension(), - originalWorld.dimensionType(), - new NoOpWorldLoadListener(), - newOpts.dimensions().get(worldDimKey).generator(), - originalWorld.isDebug(), - seed, - ImmutableList.of(), - false, - env, gen, - bukkitWorld.getBiomeProvider() - ); - try { - regenForWorld(region, extent, freshWorld, options); - } finally { - freshWorld.getChunkSource().close(false); - } - } finally { - try { - @SuppressWarnings("unchecked") - Map map = (Map) worldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException ignored) { - } - SafeFiles.tryHardToDeleteDir(tempDir); - } - } - - private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { - ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome); - if (key == null) { - return null; - } - return BiomeTypes.get(key.toString()); - } - - @SuppressWarnings("unchecked") - private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws - WorldEditException { - List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); - BlockableEventLoop executor; - try { - executor = (BlockableEventLoop) mainThreadProcessorField.get(serverWorld.getChunkSource()); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Couldn't get executor for chunk loading.", e); - } - executor.managedBlock(() -> { - // bail out early if a future fails - if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null - )) { - return false; - } - return chunkLoadings.stream().allMatch(CompletableFuture::isDone); - }); - Map chunks = new HashMap<>(); - for (CompletableFuture future : chunkLoadings) { - @Nullable - ChunkAccess chunk = future.getNow(null); - checkState(chunk != null, "Failed to generate a chunk, regen failed."); - chunks.put(chunk.getPos(), chunk); - } - - for (BlockVector3 vec : region) { - BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); - ChunkAccess chunk = chunks.get(new ChunkPos(pos)); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos); - BlockStateHolder state = ((PaperweightFaweAdapter) WorldEditPlugin - .getInstance() - .getBukkitImplAdapter()).adapt(blockData); - Objects.requireNonNull(state); - BlockEntity blockEntity = chunk.getBlockEntity(pos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - blockEntity.save(tag); - //FAWE start - BinaryTag - state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag))); - //FAWE end - } - extent.setBlock(vec, state.toBaseBlock()); - if (options.shouldRegenBiomes()) { - ChunkBiomeContainer biomeIndex = chunk.getBiomes(); - if (biomeIndex != null) { - Biome origBiome = biomeIndex.getNoiseBiome(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); - BiomeType adaptedBiome = adapt(serverWorld, origBiome); - if (adaptedBiome != null) { - extent.setBiome(vec, adaptedBiome); - } - } - } - } - } - - @SuppressWarnings("unchecked") - private List> submitChunkLoadTasks(Region region, ServerLevel serverWorld) { - ServerChunkCache chunkManager = serverWorld.getChunkSource(); - List> chunkLoadings = new ArrayList<>(); - // Pre-gen all the chunks - for (BlockVector2 chunk : region.getChunks()) { - try { - chunkLoadings.add( - ((CompletableFuture>) - getChunkFutureMainThreadMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) - ); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("Couldn't load chunk for regen.", e); - } - } - return chunkLoadings; - } - - private ResourceKey getWorldDimKey(Environment env) { - switch (env) { - case NETHER: - return LevelStem.NETHER; - case THE_END: - return LevelStem.END; - case NORMAL: - default: - return LevelStem.OVERWORLD; - } - } - - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE - ); - - @Override - public Set getSupportedSideEffects() { - return SUPPORTED_SIDE_EFFECTS; - } - - @Override - public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) { - ServerLevel originalWorld = ((CraftWorld) world).getHandle(); - - BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ())); - if (entity instanceof Clearable) { - ((Clearable) entity).clearContent(); - return true; - } - return false; - } - - // ------------------------------------------------------------------------ - // Code that is less likely to break - // ------------------------------------------------------------------------ - - /** - * Converts from a non-native NMS NBT structure to a native WorldEdit NBT - * structure. - * - * @param foreign non-native NMS NBT structure - * @return native WorldEdit NBT structure - */ - //FAWE start - BinaryTag - @Override - public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); - Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); - - for (String str : foreignKeys) { - net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); - } - return CompoundBinaryTag.from(values); - } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); - } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); - } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); - } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); - } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); - } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); - } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); - } else if (foreign instanceof net.minecraft.nbt.ListTag) { - try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); - } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); - } - } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); - } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); - } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); - } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); - } - } - - /** - * Convert a foreign NBT list tag into a native WorldEdit one. - * - * @param foreign the foreign tag - * @return the converted tag - * @throws SecurityException on error - * @throws IllegalArgumentException on error - */ - private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { - ListBinaryTag.Builder values = ListBinaryTag.builder(); - - for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); - } - - return values.build(); - } - - /** - * Converts a WorldEdit-native NBT structure to a NMS structure. - * - * @param foreign structure to convert - * @return non-native structure - */ - @Override - public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof CompoundBinaryTag) { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); - } - return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag foreignList) { - net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); - } - return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { - return net.minecraft.nbt.EndTag.INSTANCE; - } else { - throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); - } - } - //FAWE end - - @Override - public boolean supportsWatchdog() { - return watchdog != null; - } - - @Override - public void tickWatchdog() { - watchdog.tick(); - } - - private class SpigotWatchdog implements Watchdog { - - private final Field instanceField; - private final Field lastTickField; - - SpigotWatchdog() throws NoSuchFieldException { - Field instanceField = WatchdogThread.class.getDeclaredField("instance"); - instanceField.setAccessible(true); - this.instanceField = instanceField; - - Field lastTickField = WatchdogThread.class.getDeclaredField("lastTick"); - lastTickField.setAccessible(true); - this.lastTickField = lastTickField; - } - - @Override - public void tick() { - try { - WatchdogThread instance = (WatchdogThread) this.instanceField.get(null); - if ((long) lastTickField.get(instance) != 0) { - WatchdogThread.tick(); - } - } catch (IllegalAccessException e) { - LOGGER.log(Level.WARNING, "Failed to tick watchdog", e); - } - } - - } - - private static class MojangWatchdog implements Watchdog { - - private final DedicatedServer server; - private final Field tickField; - - MojangWatchdog(DedicatedServer server) throws NoSuchFieldException { - this.server = server; - Field tickField = MinecraftServer.class.getDeclaredField( - Refraction.pickName("nextTickTime", "ao") - ); - tickField.setAccessible(true); - this.tickField = tickField; - } - - @Override - public void tick() { - try { - tickField.set(server, Util.getMillis()); - } catch (IllegalAccessException ignored) { - } - } - - } - - private static class NoOpWorldLoadListener implements ChunkProgressListener { - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - } - - @Override - public void stop() { - } - - @Override - public void setChunkRadius(int radius) { - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightDataConverters.java deleted file mode 100644 index 6678bdc52..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightDataConverters.java +++ /dev/null @@ -1,2961 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.mojang.datafixers.DSL.TypeReference; -import com.mojang.datafixers.DataFixer; -import com.mojang.datafixers.DataFixerBuilder; -import com.mojang.datafixers.schemas.Schema; -import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import net.minecraft.core.Direction; -import net.minecraft.nbt.NbtOps; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.TextComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; -import net.minecraft.util.StringUtil; -import net.minecraft.util.datafix.DataFixers; -import net.minecraft.util.datafix.fixes.References; -import net.minecraft.world.item.DyeColor; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.annotation.Nullable; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executor; -import java.util.stream.Collectors; - -/** - * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) - *

- * We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy - * which is safer, faster and cleaner code. - *

- * The pre DFU code did not fail when the Source version was unknown. - *

- * This class also provides util methods for converting compounds to wrap the update call to - * receive the source version in the compound - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - - //FAWE start - BinaryTag - @SuppressWarnings("unchecked") - @Override - public T fixUp(FixType type, T original, int srcVer) { - if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_STATE) { - return (T) fixBlockState((String) original, srcVer); - } else if (type == FixTypes.ITEM_TYPE) { - return (T) fixItemType((String) original, srcVer); - } else if (type == FixTypes.BIOME) { - return (T) fixBiome((String) original, srcVer); - } - return original; - } - - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - //FAWE end - - private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update( - References.BLOCK_STATE, - dynamic, - srcVer, - DATA_VERSION - ).getValue(); - return nbtToState(fixed); - } - - private String nbtToState(net.minecraft.nbt.CompoundTag tagCompound) { - StringBuilder sb = new StringBuilder(); - sb.append(tagCompound.getString("Name")); - if (tagCompound.contains("Properties", 10)) { - sb.append('['); - net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties"); - sb.append(props - .getAllKeys() - .stream() - .map(k -> k + "=" + props.getString(k).replace("\"", "")) - .collect(Collectors.joining(","))); - sb.append(']'); - } - return sb.toString(); - } - - private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { - int propIdx = blockState.indexOf('['); - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - if (propIdx < 0) { - tag.putString("Name", blockState); - } else { - tag.putString("Name", blockState.substring(0, propIdx)); - net.minecraft.nbt.CompoundTag propTag = new net.minecraft.nbt.CompoundTag(); - String props = blockState.substring(propIdx + 1, blockState.length() - 1); - String[] propArr = props.split(","); - for (String pair : propArr) { - final String[] split = pair.split("="); - propTag.putString(split[0], split[1]); - } - tag.put("Properties", propTag); - } - return tag; - } - - private String fixBiome(String key, int srcVer) { - return fixName(key, srcVer, References.BIOME); - } - - private String fixItemType(String key, int srcVer) { - return fixName(key, srcVer, References.ITEM_NAME); - } - - private static String fixName(String key, int srcVer, TypeReference type) { - return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, net.minecraft.nbt.StringTag.valueOf(key)), srcVer, DATA_VERSION) - .getValue().getAsString(); - } - - private final PaperweightAdapter adapter; - - private static final NbtOps OPS_NBT = NbtOps.INSTANCE; - private static final int LEGACY_VERSION = 1343; - private static int DATA_VERSION; - static PaperweightDataConverters INSTANCE; - - private final Map> converters = new EnumMap<>(LegacyType.class); - private final Map> inspectors = new EnumMap<>(LegacyType.class); - - // Set on build - private DataFixer fixer; - private static final Map DFU_TO_LEGACY = new HashMap<>(); - - public enum LegacyType { - LEVEL(References.LEVEL), - PLAYER(References.PLAYER), - CHUNK(References.CHUNK), - BLOCK_ENTITY(References.BLOCK_ENTITY), - ENTITY(References.ENTITY), - ITEM_INSTANCE(References.ITEM_STACK), - OPTIONS(References.OPTIONS), - STRUCTURE(References.STRUCTURE); - - private final TypeReference type; - - LegacyType(TypeReference type) { - this.type = type; - DFU_TO_LEGACY.put(type.typeName(), this); - } - - public TypeReference getDFUType() { - return type; - } - } - - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { - super(dataVersion); - DATA_VERSION = dataVersion; - INSTANCE = this; - this.adapter = adapter; - registerConverters(); - registerInspectors(); - } - - - // Called after fixers are built and ready for FIXING - @Override - public DataFixer build(final Executor executor) { - return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); - } - - @SuppressWarnings("unchecked") - private class WrappedDataFixer implements DataFixer { - - private final DataFixer realFixer; - - WrappedDataFixer(DataFixer realFixer) { - this.realFixer = realFixer; - } - - @Override - public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { - LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); - if (sourceVer < LEGACY_VERSION && legacyType != null) { - net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); - int desiredVersion = Math.min(targetVer, LEGACY_VERSION); - - cmp = convert(legacyType, cmp, sourceVer, desiredVersion); - sourceVer = desiredVersion; - dynamic = new Dynamic(OPS_NBT, cmp); - } - return realFixer.update(type, dynamic, sourceVer, targetVer); - } - - private net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int desiredVersion - ) { - List converters = PaperweightDataConverters.this.converters.get(type); - if (converters != null && !converters.isEmpty()) { - for (DataConverter converter : converters) { - int dataVersion = converter.getDataVersion(); - if (dataVersion > sourceVer && dataVersion <= desiredVersion) { - cmp = converter.convert(cmp); - } - } - } - - List inspectors = PaperweightDataConverters.this.inspectors.get(type); - if (inspectors != null && !inspectors.isEmpty()) { - for (DataInspector inspector : inspectors) { - cmp = inspector.inspect(cmp, sourceVer, desiredVersion); - } - } - - return cmp; - } - - @Override - public Schema getSchema(int i) { - return realFixer.getSchema(i); - } - - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { - return convert(type.getDFUType(), cmp); - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type.getDFUType(), cmp, sourceVer); - } - - public static net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { - return convert(type.getDFUType(), cmp, sourceVer, targetVer); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { - int i = cmp.contains("DataVersion", 99) ? cmp.getInt("DataVersion") : -1; - return convert(type, cmp, i); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type, cmp, sourceVer, DATA_VERSION); - } - - public static net.minecraft.nbt.CompoundTag convert( - TypeReference type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { - if (sourceVer >= targetVer) { - return cmp; - } - return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer - .update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer) - .getValue(); - } - - - public interface DataInspector { - - net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); - - } - - public interface DataConverter { - - int getDataVersion(); - - net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); - - } - - - private void registerInspector(LegacyType type, DataInspector inspector) { - this.inspectors.computeIfAbsent(type, k -> new ArrayList<>()).add(inspector); - } - - private void registerConverter(LegacyType type, DataConverter converter) { - int version = converter.getDataVersion(); - - List list = this.converters.computeIfAbsent(type, k -> new ArrayList<>()); - if (!list.isEmpty() && list.get(list.size() - 1).getDataVersion() > version) { - for (int j = 0; j < list.size(); ++j) { - if (list.get(j).getDataVersion() > version) { - list.add(j, converter); - break; - } - } - } else { - list.add(converter); - } - } - - private void registerInspectors() { - registerEntityItemList("EntityHorseDonkey", "SaddleItem", "Items"); - registerEntityItemList("EntityHorseMule", "Items"); - registerEntityItemList("EntityMinecartChest", "Items"); - registerEntityItemList("EntityMinecartHopper", "Items"); - registerEntityItemList("EntityVillager", "Inventory"); - registerEntityItemListEquipment("EntityArmorStand"); - registerEntityItemListEquipment("EntityBat"); - registerEntityItemListEquipment("EntityBlaze"); - registerEntityItemListEquipment("EntityCaveSpider"); - registerEntityItemListEquipment("EntityChicken"); - registerEntityItemListEquipment("EntityCow"); - registerEntityItemListEquipment("EntityCreeper"); - registerEntityItemListEquipment("EntityEnderDragon"); - registerEntityItemListEquipment("EntityEnderman"); - registerEntityItemListEquipment("EntityEndermite"); - registerEntityItemListEquipment("EntityEvoker"); - registerEntityItemListEquipment("EntityGhast"); - registerEntityItemListEquipment("EntityGiantZombie"); - registerEntityItemListEquipment("EntityGuardian"); - registerEntityItemListEquipment("EntityGuardianElder"); - registerEntityItemListEquipment("EntityHorse"); - registerEntityItemListEquipment("EntityHorseDonkey"); - registerEntityItemListEquipment("EntityHorseMule"); - registerEntityItemListEquipment("EntityHorseSkeleton"); - registerEntityItemListEquipment("EntityHorseZombie"); - registerEntityItemListEquipment("EntityIronGolem"); - registerEntityItemListEquipment("EntityMagmaCube"); - registerEntityItemListEquipment("EntityMushroomCow"); - registerEntityItemListEquipment("EntityOcelot"); - registerEntityItemListEquipment("EntityPig"); - registerEntityItemListEquipment("EntityPigZombie"); - registerEntityItemListEquipment("EntityRabbit"); - registerEntityItemListEquipment("EntitySheep"); - registerEntityItemListEquipment("EntityShulker"); - registerEntityItemListEquipment("EntitySilverfish"); - registerEntityItemListEquipment("EntitySkeleton"); - registerEntityItemListEquipment("EntitySkeletonStray"); - registerEntityItemListEquipment("EntitySkeletonWither"); - registerEntityItemListEquipment("EntitySlime"); - registerEntityItemListEquipment("EntitySnowman"); - registerEntityItemListEquipment("EntitySpider"); - registerEntityItemListEquipment("EntitySquid"); - registerEntityItemListEquipment("EntityVex"); - registerEntityItemListEquipment("EntityVillager"); - registerEntityItemListEquipment("EntityVindicator"); - registerEntityItemListEquipment("EntityWitch"); - registerEntityItemListEquipment("EntityWither"); - registerEntityItemListEquipment("EntityWolf"); - registerEntityItemListEquipment("EntityZombie"); - registerEntityItemListEquipment("EntityZombieHusk"); - registerEntityItemListEquipment("EntityZombieVillager"); - registerEntityItemSingle("EntityFireworks", "FireworksItem"); - registerEntityItemSingle("EntityHorse", "ArmorItem"); - registerEntityItemSingle("EntityHorse", "SaddleItem"); - registerEntityItemSingle("EntityHorseMule", "SaddleItem"); - registerEntityItemSingle("EntityHorseSkeleton", "SaddleItem"); - registerEntityItemSingle("EntityHorseZombie", "SaddleItem"); - registerEntityItemSingle("EntityItem", "Item"); - registerEntityItemSingle("EntityItemFrame", "Item"); - registerEntityItemSingle("EntityPotion", "Potion"); - - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItem("TileEntityRecordPlayer", "RecordItem")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityBrewingStand", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityChest", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDispenser", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDropper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityFurnace", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityHopper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityShulkerBox", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorMobSpawnerMobs()); - registerInspector(LegacyType.CHUNK, new DataInspectorChunks()); - registerInspector(LegacyType.ENTITY, new DataInspectorCommandBlock()); - registerInspector(LegacyType.ENTITY, new DataInspectorEntityPassengers()); - registerInspector(LegacyType.ENTITY, new DataInspectorMobSpawnerMinecart()); - registerInspector(LegacyType.ENTITY, new DataInspectorVillagers()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorBlockEntity()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorEntity()); - registerInspector(LegacyType.LEVEL, new DataInspectorLevelPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayerVehicle()); - registerInspector(LegacyType.STRUCTURE, new DataInspectorStructure()); - } - - private void registerConverters() { - registerConverter(LegacyType.ENTITY, new DataConverterEquipment()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterSignText()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterMaterialId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterSpawnEgg()); - registerConverter(LegacyType.ENTITY, new DataConverterMinecart()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterMobSpawner()); - registerConverter(LegacyType.ENTITY, new DataConverterUUID()); - registerConverter(LegacyType.ENTITY, new DataConverterHealth()); - registerConverter(LegacyType.ENTITY, new DataConverterSaddle()); - registerConverter(LegacyType.ENTITY, new DataConverterHanging()); - registerConverter(LegacyType.ENTITY, new DataConverterDropChances()); - registerConverter(LegacyType.ENTITY, new DataConverterRiding()); - registerConverter(LegacyType.ENTITY, new DataConverterArmorStand()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBook()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterCookedFish()); - registerConverter(LegacyType.ENTITY, new DataConverterZombie()); - registerConverter(LegacyType.OPTIONS, new DataConverterVBO()); - registerConverter(LegacyType.ENTITY, new DataConverterGuardian()); - registerConverter(LegacyType.ENTITY, new DataConverterSkeleton()); - registerConverter(LegacyType.ENTITY, new DataConverterZombieType()); - registerConverter(LegacyType.ENTITY, new DataConverterHorse()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterTileEntity()); - registerConverter(LegacyType.ENTITY, new DataConverterEntity()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBanner()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionWater()); - registerConverter(LegacyType.ENTITY, new DataConverterShulker()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterShulkerBoxItem()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterShulkerBoxBlock()); - registerConverter(LegacyType.OPTIONS, new DataConverterLang()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterTotem()); - registerConverter(LegacyType.CHUNK, new DataConverterBedBlock()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBedItem()); - } - - private void registerEntityItemList(String type, String... keys) { - registerInspector(LegacyType.ENTITY, new DataInspectorItemList(type, keys)); - } - - private void registerEntityItemSingle(String type, String key) { - registerInspector(LegacyType.ENTITY, new DataInspectorItem(type, key)); - } - - private void registerEntityItemListEquipment(String type) { - registerEntityItemList(type, "ArmorItems", "HandItems"); - } - - private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); - - static { - final Map map = OLD_ID_TO_KEY_MAP; - map.put("EntityItem", new ResourceLocation("item")); - map.put("EntityExperienceOrb", new ResourceLocation("xp_orb")); - map.put("EntityAreaEffectCloud", new ResourceLocation("area_effect_cloud")); - map.put("EntityGuardianElder", new ResourceLocation("elder_guardian")); - map.put("EntitySkeletonWither", new ResourceLocation("wither_skeleton")); - map.put("EntitySkeletonStray", new ResourceLocation("stray")); - map.put("EntityEgg", new ResourceLocation("egg")); - map.put("EntityLeash", new ResourceLocation("leash_knot")); - map.put("EntityPainting", new ResourceLocation("painting")); - map.put("EntityTippedArrow", new ResourceLocation("arrow")); - map.put("EntitySnowball", new ResourceLocation("snowball")); - map.put("EntityLargeFireball", new ResourceLocation("fireball")); - map.put("EntitySmallFireball", new ResourceLocation("small_fireball")); - map.put("EntityEnderPearl", new ResourceLocation("ender_pearl")); - map.put("EntityEnderSignal", new ResourceLocation("eye_of_ender_signal")); - map.put("EntityPotion", new ResourceLocation("potion")); - map.put("EntityThrownExpBottle", new ResourceLocation("xp_bottle")); - map.put("EntityItemFrame", new ResourceLocation("item_frame")); - map.put("EntityWitherSkull", new ResourceLocation("wither_skull")); - map.put("EntityTNTPrimed", new ResourceLocation("tnt")); - map.put("EntityFallingBlock", new ResourceLocation("falling_block")); - map.put("EntityFireworks", new ResourceLocation("fireworks_rocket")); - map.put("EntityZombieHusk", new ResourceLocation("husk")); - map.put("EntitySpectralArrow", new ResourceLocation("spectral_arrow")); - map.put("EntityShulkerBullet", new ResourceLocation("shulker_bullet")); - map.put("EntityDragonFireball", new ResourceLocation("dragon_fireball")); - map.put("EntityZombieVillager", new ResourceLocation("zombie_villager")); - map.put("EntityHorseSkeleton", new ResourceLocation("skeleton_horse")); - map.put("EntityHorseZombie", new ResourceLocation("zombie_horse")); - map.put("EntityArmorStand", new ResourceLocation("armor_stand")); - map.put("EntityHorseDonkey", new ResourceLocation("donkey")); - map.put("EntityHorseMule", new ResourceLocation("mule")); - map.put("EntityEvokerFangs", new ResourceLocation("evocation_fangs")); - map.put("EntityEvoker", new ResourceLocation("evocation_illager")); - map.put("EntityVex", new ResourceLocation("vex")); - map.put("EntityVindicator", new ResourceLocation("vindication_illager")); - map.put("EntityIllagerIllusioner", new ResourceLocation("illusion_illager")); - map.put("EntityMinecartCommandBlock", new ResourceLocation("commandblock_minecart")); - map.put("EntityBoat", new ResourceLocation("boat")); - map.put("EntityMinecartRideable", new ResourceLocation("minecart")); - map.put("EntityMinecartChest", new ResourceLocation("chest_minecart")); - map.put("EntityMinecartFurnace", new ResourceLocation("furnace_minecart")); - map.put("EntityMinecartTNT", new ResourceLocation("tnt_minecart")); - map.put("EntityMinecartHopper", new ResourceLocation("hopper_minecart")); - map.put("EntityMinecartMobSpawner", new ResourceLocation("spawner_minecart")); - map.put("EntityCreeper", new ResourceLocation("creeper")); - map.put("EntitySkeleton", new ResourceLocation("skeleton")); - map.put("EntitySpider", new ResourceLocation("spider")); - map.put("EntityGiantZombie", new ResourceLocation("giant")); - map.put("EntityZombie", new ResourceLocation("zombie")); - map.put("EntitySlime", new ResourceLocation("slime")); - map.put("EntityGhast", new ResourceLocation("ghast")); - map.put("EntityPigZombie", new ResourceLocation("zombie_pigman")); - map.put("EntityEnderman", new ResourceLocation("enderman")); - map.put("EntityCaveSpider", new ResourceLocation("cave_spider")); - map.put("EntitySilverfish", new ResourceLocation("silverfish")); - map.put("EntityBlaze", new ResourceLocation("blaze")); - map.put("EntityMagmaCube", new ResourceLocation("magma_cube")); - map.put("EntityEnderDragon", new ResourceLocation("ender_dragon")); - map.put("EntityWither", new ResourceLocation("wither")); - map.put("EntityBat", new ResourceLocation("bat")); - map.put("EntityWitch", new ResourceLocation("witch")); - map.put("EntityEndermite", new ResourceLocation("endermite")); - map.put("EntityGuardian", new ResourceLocation("guardian")); - map.put("EntityShulker", new ResourceLocation("shulker")); - map.put("EntityPig", new ResourceLocation("pig")); - map.put("EntitySheep", new ResourceLocation("sheep")); - map.put("EntityCow", new ResourceLocation("cow")); - map.put("EntityChicken", new ResourceLocation("chicken")); - map.put("EntitySquid", new ResourceLocation("squid")); - map.put("EntityWolf", new ResourceLocation("wolf")); - map.put("EntityMushroomCow", new ResourceLocation("mooshroom")); - map.put("EntitySnowman", new ResourceLocation("snowman")); - map.put("EntityOcelot", new ResourceLocation("ocelot")); - map.put("EntityIronGolem", new ResourceLocation("villager_golem")); - map.put("EntityHorse", new ResourceLocation("horse")); - map.put("EntityRabbit", new ResourceLocation("rabbit")); - map.put("EntityPolarBear", new ResourceLocation("polar_bear")); - map.put("EntityLlama", new ResourceLocation("llama")); - map.put("EntityLlamaSpit", new ResourceLocation("llama_spit")); - map.put("EntityParrot", new ResourceLocation("parrot")); - map.put("EntityVillager", new ResourceLocation("villager")); - map.put("EntityEnderCrystal", new ResourceLocation("ender_crystal")); - map.put("TileEntityFurnace", new ResourceLocation("furnace")); - map.put("TileEntityChest", new ResourceLocation("chest")); - map.put("TileEntityEnderChest", new ResourceLocation("ender_chest")); - map.put("TileEntityRecordPlayer", new ResourceLocation("jukebox")); - map.put("TileEntityDispenser", new ResourceLocation("dispenser")); - map.put("TileEntityDropper", new ResourceLocation("dropper")); - map.put("TileEntitySign", new ResourceLocation("sign")); - map.put("TileEntityMobSpawner", new ResourceLocation("mob_spawner")); - map.put("TileEntityNote", new ResourceLocation("noteblock")); - map.put("TileEntityPiston", new ResourceLocation("piston")); - map.put("TileEntityBrewingStand", new ResourceLocation("brewing_stand")); - map.put("TileEntityEnchantTable", new ResourceLocation("enchanting_table")); - map.put("TileEntityEnderPortal", new ResourceLocation("end_portal")); - map.put("TileEntityBeacon", new ResourceLocation("beacon")); - map.put("TileEntitySkull", new ResourceLocation("skull")); - map.put("TileEntityLightDetector", new ResourceLocation("daylight_detector")); - map.put("TileEntityHopper", new ResourceLocation("hopper")); - map.put("TileEntityComparator", new ResourceLocation("comparator")); - map.put("TileEntityFlowerPot", new ResourceLocation("flower_pot")); - map.put("TileEntityBanner", new ResourceLocation("banner")); - map.put("TileEntityStructure", new ResourceLocation("structure_block")); - map.put("TileEntityEndGateway", new ResourceLocation("end_gateway")); - map.put("TileEntityCommand", new ResourceLocation("command_block")); - map.put("TileEntityShulkerBox", new ResourceLocation("shulker_box")); - map.put("TileEntityBed", new ResourceLocation("bed")); - } - - private static ResourceLocation getKey(String type) { - final ResourceLocation key = OLD_ID_TO_KEY_MAP.get(type); - if (key == null) { - throw new IllegalArgumentException("Unknown mapping for " + type); - } - return key; - } - - private static void convertCompound( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - String key, - int sourceVer, - int targetVer - ) { - cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer)); - } - - private static void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - if (nbttagcompound.contains(key, 10)) { - convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); - } - } - - private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - if (nbttagcompound.contains(key, 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound.getList(key, 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); - } - } - - } - - private static class DataConverterEquipment implements DataConverter { - - DataConverterEquipment() { - } - - public int getDataVersion() { - return 100; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Equipment", 10); - net.minecraft.nbt.ListTag nbttaglist1; - - if (!nbttaglist.isEmpty() && !cmp.contains("HandItems", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); - nbttaglist1.add(nbttaglist.get(0)); - nbttaglist1.add(new net.minecraft.nbt.CompoundTag()); - cmp.put("HandItems", nbttaglist1); - } - - if (nbttaglist.size() > 1 && !cmp.contains("ArmorItem", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); - nbttaglist1.add(nbttaglist.get(1)); - nbttaglist1.add(nbttaglist.get(2)); - nbttaglist1.add(nbttaglist.get(3)); - nbttaglist1.add(nbttaglist.get(4)); - cmp.put("ArmorItems", nbttaglist1); - } - - cmp.remove("Equipment"); - if (cmp.contains("DropChances", 9)) { - nbttaglist1 = cmp.getList("DropChances", 5); - net.minecraft.nbt.ListTag nbttaglist2; - - if (!cmp.contains("HandDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(0))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(0.0F)); - cmp.put("HandDropChances", nbttaglist2); - } - - if (!cmp.contains("ArmorDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(1))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(2))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(3))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(4))); - cmp.put("ArmorDropChances", nbttaglist2); - } - - cmp.remove("DropChances"); - } - - return cmp; - } - - } - - private static class DataInspectorBlockEntity implements DataInspector { - - private static final Map b = Maps.newHashMap(); - private static final Map c = Maps.newHashMap(); - - DataInspectorBlockEntity() { - } - - @Nullable - private static String convertEntityId(int i, String s) { - String key = new ResourceLocation(s).toString(); - if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { - return DataInspectorBlockEntity.b.get(key); - } else { - return DataInspectorBlockEntity.c.get(key); - } - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (!cmp.contains("tag", 10)) { - return cmp; - } else { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - String s = cmp.getString("id"); - String s1 = convertEntityId(sourceVer, s); - boolean flag; - - if (s1 == null) { - // CraftBukkit - Remove unnecessary warning (occurs when deserializing a Shulker Box item) - // DataInspectorBlockEntity.a.warn("Unable to resolve BlockEntity for ItemInstance: {}", s); - flag = false; - } else { - flag = !nbttagcompound2.contains("id"); - nbttagcompound2.putString("id", s1); - } - - convert(LegacyType.BLOCK_ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - } - - return cmp; - } - } - - static { - Map map = DataInspectorBlockEntity.b; - - map.put("minecraft:furnace", "Furnace"); - map.put("minecraft:lit_furnace", "Furnace"); - map.put("minecraft:chest", "Chest"); - map.put("minecraft:trapped_chest", "Chest"); - map.put("minecraft:ender_chest", "EnderChest"); - map.put("minecraft:jukebox", "RecordPlayer"); - map.put("minecraft:dispenser", "Trap"); - map.put("minecraft:dropper", "Dropper"); - map.put("minecraft:sign", "Sign"); - map.put("minecraft:mob_spawner", "MobSpawner"); - map.put("minecraft:noteblock", "Music"); - map.put("minecraft:brewing_stand", "Cauldron"); - map.put("minecraft:enhanting_table", "EnchantTable"); - map.put("minecraft:command_block", "CommandBlock"); - map.put("minecraft:beacon", "Beacon"); - map.put("minecraft:skull", "Skull"); - map.put("minecraft:daylight_detector", "DLDetector"); - map.put("minecraft:hopper", "Hopper"); - map.put("minecraft:banner", "Banner"); - map.put("minecraft:flower_pot", "FlowerPot"); - map.put("minecraft:repeating_command_block", "CommandBlock"); - map.put("minecraft:chain_command_block", "CommandBlock"); - map.put("minecraft:standing_sign", "Sign"); - map.put("minecraft:wall_sign", "Sign"); - map.put("minecraft:piston_head", "Piston"); - map.put("minecraft:daylight_detector_inverted", "DLDetector"); - map.put("minecraft:unpowered_comparator", "Comparator"); - map.put("minecraft:powered_comparator", "Comparator"); - map.put("minecraft:wall_banner", "Banner"); - map.put("minecraft:standing_banner", "Banner"); - map.put("minecraft:structure_block", "Structure"); - map.put("minecraft:end_portal", "Airportal"); - map.put("minecraft:end_gateway", "EndGateway"); - map.put("minecraft:shield", "Shield"); - map = DataInspectorBlockEntity.c; - map.put("minecraft:furnace", "minecraft:furnace"); - map.put("minecraft:lit_furnace", "minecraft:furnace"); - map.put("minecraft:chest", "minecraft:chest"); - map.put("minecraft:trapped_chest", "minecraft:chest"); - map.put("minecraft:ender_chest", "minecraft:enderchest"); - map.put("minecraft:jukebox", "minecraft:jukebox"); - map.put("minecraft:dispenser", "minecraft:dispenser"); - map.put("minecraft:dropper", "minecraft:dropper"); - map.put("minecraft:sign", "minecraft:sign"); - map.put("minecraft:mob_spawner", "minecraft:mob_spawner"); - map.put("minecraft:noteblock", "minecraft:noteblock"); - map.put("minecraft:brewing_stand", "minecraft:brewing_stand"); - map.put("minecraft:enhanting_table", "minecraft:enchanting_table"); - map.put("minecraft:command_block", "minecraft:command_block"); - map.put("minecraft:beacon", "minecraft:beacon"); - map.put("minecraft:skull", "minecraft:skull"); - map.put("minecraft:daylight_detector", "minecraft:daylight_detector"); - map.put("minecraft:hopper", "minecraft:hopper"); - map.put("minecraft:banner", "minecraft:banner"); - map.put("minecraft:flower_pot", "minecraft:flower_pot"); - map.put("minecraft:repeating_command_block", "minecraft:command_block"); - map.put("minecraft:chain_command_block", "minecraft:command_block"); - map.put("minecraft:shulker_box", "minecraft:shulker_box"); - map.put("minecraft:white_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:orange_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:magenta_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:light_blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:yellow_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:lime_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:pink_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:gray_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:silver_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:cyan_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:purple_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:brown_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:green_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:red_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:black_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:bed", "minecraft:bed"); - map.put("minecraft:standing_sign", "minecraft:sign"); - map.put("minecraft:wall_sign", "minecraft:sign"); - map.put("minecraft:piston_head", "minecraft:piston"); - map.put("minecraft:daylight_detector_inverted", "minecraft:daylight_detector"); - map.put("minecraft:unpowered_comparator", "minecraft:comparator"); - map.put("minecraft:powered_comparator", "minecraft:comparator"); - map.put("minecraft:wall_banner", "minecraft:banner"); - map.put("minecraft:standing_banner", "minecraft:banner"); - map.put("minecraft:structure_block", "minecraft:structure_block"); - map.put("minecraft:end_portal", "minecraft:end_portal"); - map.put("minecraft:end_gateway", "minecraft:end_gateway"); - map.put("minecraft:shield", "minecraft:shield"); - } - } - - private static class DataInspectorEntity implements DataInspector { - - private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); - - DataInspectorEntity() { - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("EntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); - String s = cmp.getString("id"); - String s1; - - if ("minecraft:armor_stand".equals(s)) { - s1 = sourceVer < 515 ? "ArmorStand" : "minecraft:armor_stand"; - } else { - if (!"minecraft:spawn_egg".equals(s)) { - return cmp; - } - - s1 = nbttagcompound2.getString("id"); - } - - boolean flag; - - flag = !nbttagcompound2.contains("id", 8); - nbttagcompound2.putString("id", s1); - - convert(LegacyType.ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - } - - return cmp; - } - - } - - - private abstract static class DataInspectorTagged implements DataInspector { - - private final ResourceLocation key; - - DataInspectorTagged(String type) { - this.key = getKey(type); - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (this.key.equals(new ResourceLocation(cmp.getString("id")))) { - cmp = this.inspectChecked(cmp, sourceVer, targetVer); - } - - return cmp; - } - - abstract net.minecraft.nbt.CompoundTag inspectChecked( - net.minecraft.nbt.CompoundTag nbttagcompound, - int sourceVer, - int targetVer - ); - - } - - private static class DataInspectorItemList extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItemList(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String s : this.keys) { - PaperweightDataConverters.convertItems(nbttagcompound, s, sourceVer, targetVer); - } - - return nbttagcompound; - } - - } - - private static class DataInspectorItem extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItem(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String key : this.keys) { - PaperweightDataConverters.convertItem(nbttagcompound, key, sourceVer, targetVer); - } - - return nbttagcompound; - } - - } - - private static class DataConverterMaterialId implements DataConverter { - - private static final String[] materials = new String[2268]; - - DataConverterMaterialId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 99)) { - short short0 = cmp.getShort("id"); - - if (short0 > 0 && short0 < materials.length && materials[short0] != null) { - cmp.putString("id", materials[short0]); - } - } - - return cmp; - } - - static { - materials[1] = "minecraft:stone"; - materials[2] = "minecraft:grass"; - materials[3] = "minecraft:dirt"; - materials[4] = "minecraft:cobblestone"; - materials[5] = "minecraft:planks"; - materials[6] = "minecraft:sapling"; - materials[7] = "minecraft:bedrock"; - materials[8] = "minecraft:flowing_water"; - materials[9] = "minecraft:water"; - materials[10] = "minecraft:flowing_lava"; - materials[11] = "minecraft:lava"; - materials[12] = "minecraft:sand"; - materials[13] = "minecraft:gravel"; - materials[14] = "minecraft:gold_ore"; - materials[15] = "minecraft:iron_ore"; - materials[16] = "minecraft:coal_ore"; - materials[17] = "minecraft:log"; - materials[18] = "minecraft:leaves"; - materials[19] = "minecraft:sponge"; - materials[20] = "minecraft:glass"; - materials[21] = "minecraft:lapis_ore"; - materials[22] = "minecraft:lapis_block"; - materials[23] = "minecraft:dispenser"; - materials[24] = "minecraft:sandstone"; - materials[25] = "minecraft:noteblock"; - materials[27] = "minecraft:golden_rail"; - materials[28] = "minecraft:detector_rail"; - materials[29] = "minecraft:sticky_piston"; - materials[30] = "minecraft:web"; - materials[31] = "minecraft:tallgrass"; - materials[32] = "minecraft:deadbush"; - materials[33] = "minecraft:piston"; - materials[35] = "minecraft:wool"; - materials[37] = "minecraft:yellow_flower"; - materials[38] = "minecraft:red_flower"; - materials[39] = "minecraft:brown_mushroom"; - materials[40] = "minecraft:red_mushroom"; - materials[41] = "minecraft:gold_block"; - materials[42] = "minecraft:iron_block"; - materials[43] = "minecraft:double_stone_slab"; - materials[44] = "minecraft:stone_slab"; - materials[45] = "minecraft:brick_block"; - materials[46] = "minecraft:tnt"; - materials[47] = "minecraft:bookshelf"; - materials[48] = "minecraft:mossy_cobblestone"; - materials[49] = "minecraft:obsidian"; - materials[50] = "minecraft:torch"; - materials[51] = "minecraft:fire"; - materials[52] = "minecraft:mob_spawner"; - materials[53] = "minecraft:oak_stairs"; - materials[54] = "minecraft:chest"; - materials[56] = "minecraft:diamond_ore"; - materials[57] = "minecraft:diamond_block"; - materials[58] = "minecraft:crafting_table"; - materials[60] = "minecraft:farmland"; - materials[61] = "minecraft:furnace"; - materials[62] = "minecraft:lit_furnace"; - materials[65] = "minecraft:ladder"; - materials[66] = "minecraft:rail"; - materials[67] = "minecraft:stone_stairs"; - materials[69] = "minecraft:lever"; - materials[70] = "minecraft:stone_pressure_plate"; - materials[72] = "minecraft:wooden_pressure_plate"; - materials[73] = "minecraft:redstone_ore"; - materials[76] = "minecraft:redstone_torch"; - materials[77] = "minecraft:stone_button"; - materials[78] = "minecraft:snow_layer"; - materials[79] = "minecraft:ice"; - materials[80] = "minecraft:snow"; - materials[81] = "minecraft:cactus"; - materials[82] = "minecraft:clay"; - materials[84] = "minecraft:jukebox"; - materials[85] = "minecraft:fence"; - materials[86] = "minecraft:pumpkin"; - materials[87] = "minecraft:netherrack"; - materials[88] = "minecraft:soul_sand"; - materials[89] = "minecraft:glowstone"; - materials[90] = "minecraft:portal"; - materials[91] = "minecraft:lit_pumpkin"; - materials[95] = "minecraft:stained_glass"; - materials[96] = "minecraft:trapdoor"; - materials[97] = "minecraft:monster_egg"; - materials[98] = "minecraft:stonebrick"; - materials[99] = "minecraft:brown_mushroom_block"; - materials[100] = "minecraft:red_mushroom_block"; - materials[101] = "minecraft:iron_bars"; - materials[102] = "minecraft:glass_pane"; - materials[103] = "minecraft:melon_block"; - materials[106] = "minecraft:vine"; - materials[107] = "minecraft:fence_gate"; - materials[108] = "minecraft:brick_stairs"; - materials[109] = "minecraft:stone_brick_stairs"; - materials[110] = "minecraft:mycelium"; - materials[111] = "minecraft:waterlily"; - materials[112] = "minecraft:nether_brick"; - materials[113] = "minecraft:nether_brick_fence"; - materials[114] = "minecraft:nether_brick_stairs"; - materials[116] = "minecraft:enchanting_table"; - materials[119] = "minecraft:end_portal"; - materials[120] = "minecraft:end_portal_frame"; - materials[121] = "minecraft:end_stone"; - materials[122] = "minecraft:dragon_egg"; - materials[123] = "minecraft:redstone_lamp"; - materials[125] = "minecraft:double_wooden_slab"; - materials[126] = "minecraft:wooden_slab"; - materials[127] = "minecraft:cocoa"; - materials[128] = "minecraft:sandstone_stairs"; - materials[129] = "minecraft:emerald_ore"; - materials[130] = "minecraft:ender_chest"; - materials[131] = "minecraft:tripwire_hook"; - materials[133] = "minecraft:emerald_block"; - materials[134] = "minecraft:spruce_stairs"; - materials[135] = "minecraft:birch_stairs"; - materials[136] = "minecraft:jungle_stairs"; - materials[137] = "minecraft:command_block"; - materials[138] = "minecraft:beacon"; - materials[139] = "minecraft:cobblestone_wall"; - materials[141] = "minecraft:carrots"; - materials[142] = "minecraft:potatoes"; - materials[143] = "minecraft:wooden_button"; - materials[145] = "minecraft:anvil"; - materials[146] = "minecraft:trapped_chest"; - materials[147] = "minecraft:light_weighted_pressure_plate"; - materials[148] = "minecraft:heavy_weighted_pressure_plate"; - materials[151] = "minecraft:daylight_detector"; - materials[152] = "minecraft:redstone_block"; - materials[153] = "minecraft:quartz_ore"; - materials[154] = "minecraft:hopper"; - materials[155] = "minecraft:quartz_block"; - materials[156] = "minecraft:quartz_stairs"; - materials[157] = "minecraft:activator_rail"; - materials[158] = "minecraft:dropper"; - materials[159] = "minecraft:stained_hardened_clay"; - materials[160] = "minecraft:stained_glass_pane"; - materials[161] = "minecraft:leaves2"; - materials[162] = "minecraft:log2"; - materials[163] = "minecraft:acacia_stairs"; - materials[164] = "minecraft:dark_oak_stairs"; - materials[170] = "minecraft:hay_block"; - materials[171] = "minecraft:carpet"; - materials[172] = "minecraft:hardened_clay"; - materials[173] = "minecraft:coal_block"; - materials[174] = "minecraft:packed_ice"; - materials[175] = "minecraft:double_plant"; - materials[256] = "minecraft:iron_shovel"; - materials[257] = "minecraft:iron_pickaxe"; - materials[258] = "minecraft:iron_axe"; - materials[259] = "minecraft:flint_and_steel"; - materials[260] = "minecraft:apple"; - materials[261] = "minecraft:bow"; - materials[262] = "minecraft:arrow"; - materials[263] = "minecraft:coal"; - materials[264] = "minecraft:diamond"; - materials[265] = "minecraft:iron_ingot"; - materials[266] = "minecraft:gold_ingot"; - materials[267] = "minecraft:iron_sword"; - materials[268] = "minecraft:wooden_sword"; - materials[269] = "minecraft:wooden_shovel"; - materials[270] = "minecraft:wooden_pickaxe"; - materials[271] = "minecraft:wooden_axe"; - materials[272] = "minecraft:stone_sword"; - materials[273] = "minecraft:stone_shovel"; - materials[274] = "minecraft:stone_pickaxe"; - materials[275] = "minecraft:stone_axe"; - materials[276] = "minecraft:diamond_sword"; - materials[277] = "minecraft:diamond_shovel"; - materials[278] = "minecraft:diamond_pickaxe"; - materials[279] = "minecraft:diamond_axe"; - materials[280] = "minecraft:stick"; - materials[281] = "minecraft:bowl"; - materials[282] = "minecraft:mushroom_stew"; - materials[283] = "minecraft:golden_sword"; - materials[284] = "minecraft:golden_shovel"; - materials[285] = "minecraft:golden_pickaxe"; - materials[286] = "minecraft:golden_axe"; - materials[287] = "minecraft:string"; - materials[288] = "minecraft:feather"; - materials[289] = "minecraft:gunpowder"; - materials[290] = "minecraft:wooden_hoe"; - materials[291] = "minecraft:stone_hoe"; - materials[292] = "minecraft:iron_hoe"; - materials[293] = "minecraft:diamond_hoe"; - materials[294] = "minecraft:golden_hoe"; - materials[295] = "minecraft:wheat_seeds"; - materials[296] = "minecraft:wheat"; - materials[297] = "minecraft:bread"; - materials[298] = "minecraft:leather_helmet"; - materials[299] = "minecraft:leather_chestplate"; - materials[300] = "minecraft:leather_leggings"; - materials[301] = "minecraft:leather_boots"; - materials[302] = "minecraft:chainmail_helmet"; - materials[303] = "minecraft:chainmail_chestplate"; - materials[304] = "minecraft:chainmail_leggings"; - materials[305] = "minecraft:chainmail_boots"; - materials[306] = "minecraft:iron_helmet"; - materials[307] = "minecraft:iron_chestplate"; - materials[308] = "minecraft:iron_leggings"; - materials[309] = "minecraft:iron_boots"; - materials[310] = "minecraft:diamond_helmet"; - materials[311] = "minecraft:diamond_chestplate"; - materials[312] = "minecraft:diamond_leggings"; - materials[313] = "minecraft:diamond_boots"; - materials[314] = "minecraft:golden_helmet"; - materials[315] = "minecraft:golden_chestplate"; - materials[316] = "minecraft:golden_leggings"; - materials[317] = "minecraft:golden_boots"; - materials[318] = "minecraft:flint"; - materials[319] = "minecraft:porkchop"; - materials[320] = "minecraft:cooked_porkchop"; - materials[321] = "minecraft:painting"; - materials[322] = "minecraft:golden_apple"; - materials[323] = "minecraft:sign"; - materials[324] = "minecraft:wooden_door"; - materials[325] = "minecraft:bucket"; - materials[326] = "minecraft:water_bucket"; - materials[327] = "minecraft:lava_bucket"; - materials[328] = "minecraft:minecart"; - materials[329] = "minecraft:saddle"; - materials[330] = "minecraft:iron_door"; - materials[331] = "minecraft:redstone"; - materials[332] = "minecraft:snowball"; - materials[333] = "minecraft:boat"; - materials[334] = "minecraft:leather"; - materials[335] = "minecraft:milk_bucket"; - materials[336] = "minecraft:brick"; - materials[337] = "minecraft:clay_ball"; - materials[338] = "minecraft:reeds"; - materials[339] = "minecraft:paper"; - materials[340] = "minecraft:book"; - materials[341] = "minecraft:slime_ball"; - materials[342] = "minecraft:chest_minecart"; - materials[343] = "minecraft:furnace_minecart"; - materials[344] = "minecraft:egg"; - materials[345] = "minecraft:compass"; - materials[346] = "minecraft:fishing_rod"; - materials[347] = "minecraft:clock"; - materials[348] = "minecraft:glowstone_dust"; - materials[349] = "minecraft:fish"; - materials[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish - materials[351] = "minecraft:dye"; - materials[352] = "minecraft:bone"; - materials[353] = "minecraft:sugar"; - materials[354] = "minecraft:cake"; - materials[355] = "minecraft:bed"; - materials[356] = "minecraft:repeater"; - materials[357] = "minecraft:cookie"; - materials[358] = "minecraft:filled_map"; - materials[359] = "minecraft:shears"; - materials[360] = "minecraft:melon"; - materials[361] = "minecraft:pumpkin_seeds"; - materials[362] = "minecraft:melon_seeds"; - materials[363] = "minecraft:beef"; - materials[364] = "minecraft:cooked_beef"; - materials[365] = "minecraft:chicken"; - materials[366] = "minecraft:cooked_chicken"; - materials[367] = "minecraft:rotten_flesh"; - materials[368] = "minecraft:ender_pearl"; - materials[369] = "minecraft:blaze_rod"; - materials[370] = "minecraft:ghast_tear"; - materials[371] = "minecraft:gold_nugget"; - materials[372] = "minecraft:nether_wart"; - materials[373] = "minecraft:potion"; - materials[374] = "minecraft:glass_bottle"; - materials[375] = "minecraft:spider_eye"; - materials[376] = "minecraft:fermented_spider_eye"; - materials[377] = "minecraft:blaze_powder"; - materials[378] = "minecraft:magma_cream"; - materials[379] = "minecraft:brewing_stand"; - materials[380] = "minecraft:cauldron"; - materials[381] = "minecraft:ender_eye"; - materials[382] = "minecraft:speckled_melon"; - materials[383] = "minecraft:spawn_egg"; - materials[384] = "minecraft:experience_bottle"; - materials[385] = "minecraft:fire_charge"; - materials[386] = "minecraft:writable_book"; - materials[387] = "minecraft:written_book"; - materials[388] = "minecraft:emerald"; - materials[389] = "minecraft:item_frame"; - materials[390] = "minecraft:flower_pot"; - materials[391] = "minecraft:carrot"; - materials[392] = "minecraft:potato"; - materials[393] = "minecraft:baked_potato"; - materials[394] = "minecraft:poisonous_potato"; - materials[395] = "minecraft:map"; - materials[396] = "minecraft:golden_carrot"; - materials[397] = "minecraft:skull"; - materials[398] = "minecraft:carrot_on_a_stick"; - materials[399] = "minecraft:nether_star"; - materials[400] = "minecraft:pumpkin_pie"; - materials[401] = "minecraft:fireworks"; - materials[402] = "minecraft:firework_charge"; - materials[403] = "minecraft:enchanted_book"; - materials[404] = "minecraft:comparator"; - materials[405] = "minecraft:netherbrick"; - materials[406] = "minecraft:quartz"; - materials[407] = "minecraft:tnt_minecart"; - materials[408] = "minecraft:hopper_minecart"; - materials[417] = "minecraft:iron_horse_armor"; - materials[418] = "minecraft:golden_horse_armor"; - materials[419] = "minecraft:diamond_horse_armor"; - materials[420] = "minecraft:lead"; - materials[421] = "minecraft:name_tag"; - materials[422] = "minecraft:command_block_minecart"; - materials[2256] = "minecraft:record_13"; - materials[2257] = "minecraft:record_cat"; - materials[2258] = "minecraft:record_blocks"; - materials[2259] = "minecraft:record_chirp"; - materials[2260] = "minecraft:record_far"; - materials[2261] = "minecraft:record_mall"; - materials[2262] = "minecraft:record_mellohi"; - materials[2263] = "minecraft:record_stal"; - materials[2264] = "minecraft:record_strad"; - materials[2265] = "minecraft:record_ward"; - materials[2266] = "minecraft:record_11"; - materials[2267] = "minecraft:record_wait"; - // Paper start - materials[409] = "minecraft:prismarine_shard"; - materials[410] = "minecraft:prismarine_crystals"; - materials[411] = "minecraft:rabbit"; - materials[412] = "minecraft:cooked_rabbit"; - materials[413] = "minecraft:rabbit_stew"; - materials[414] = "minecraft:rabbit_foot"; - materials[415] = "minecraft:rabbit_hide"; - materials[416] = "minecraft:armor_stand"; - materials[423] = "minecraft:mutton"; - materials[424] = "minecraft:cooked_mutton"; - materials[425] = "minecraft:banner"; - materials[426] = "minecraft:end_crystal"; - materials[427] = "minecraft:spruce_door"; - materials[428] = "minecraft:birch_door"; - materials[429] = "minecraft:jungle_door"; - materials[430] = "minecraft:acacia_door"; - materials[431] = "minecraft:dark_oak_door"; - materials[432] = "minecraft:chorus_fruit"; - materials[433] = "minecraft:chorus_fruit_popped"; - materials[434] = "minecraft:beetroot"; - materials[435] = "minecraft:beetroot_seeds"; - materials[436] = "minecraft:beetroot_soup"; - materials[437] = "minecraft:dragon_breath"; - materials[438] = "minecraft:splash_potion"; - materials[439] = "minecraft:spectral_arrow"; - materials[440] = "minecraft:tipped_arrow"; - materials[441] = "minecraft:lingering_potion"; - materials[442] = "minecraft:shield"; - materials[443] = "minecraft:elytra"; - materials[444] = "minecraft:spruce_boat"; - materials[445] = "minecraft:birch_boat"; - materials[446] = "minecraft:jungle_boat"; - materials[447] = "minecraft:acacia_boat"; - materials[448] = "minecraft:dark_oak_boat"; - materials[449] = "minecraft:totem_of_undying"; - materials[450] = "minecraft:shulker_shell"; - materials[452] = "minecraft:iron_nugget"; - materials[453] = "minecraft:knowledge_book"; - // Paper end - } - } - - private static class DataConverterArmorStand implements DataConverter { - - DataConverterArmorStand() { - } - - public int getDataVersion() { - return 147; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("ArmorStand".equals(cmp.getString("id")) && cmp.getBoolean("Silent") && !cmp.getBoolean("Marker")) { - cmp.remove("Silent"); - } - - return cmp; - } - - } - - private static class DataConverterBanner implements DataConverter { - - DataConverterBanner() { - } - - public int getDataVersion() { - return 804; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:banner".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - - if (nbttagcompound2.contains("Base", 99)) { - cmp.putShort("Damage", (short) (nbttagcompound2.getShort("Base") & 15)); - if (nbttagcompound1.contains("display", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); - - if (nbttagcompound3.contains("Lore", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); - - if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0))) { - return cmp; - } - } - } - - nbttagcompound2.remove("Base"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - } - } - } - - return cmp; - } - - } - - private static class DataConverterPotionId implements DataConverter { - - private static final String[] potions = new String[128]; - - DataConverterPotionId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:potion".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - short short0 = cmp.getShort("Damage"); - - if (!nbttagcompound1.contains("Potion", 8)) { - String s = DataConverterPotionId.potions[short0 & 127]; - - nbttagcompound1.putString("Potion", s == null ? "minecraft:water" : s); - cmp.put("tag", nbttagcompound1); - if ((short0 & 16384) == 16384) { - cmp.putString("id", "minecraft:splash_potion"); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - - static { - DataConverterPotionId.potions[0] = "minecraft:water"; - DataConverterPotionId.potions[1] = "minecraft:regeneration"; - DataConverterPotionId.potions[2] = "minecraft:swiftness"; - DataConverterPotionId.potions[3] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[4] = "minecraft:poison"; - DataConverterPotionId.potions[5] = "minecraft:healing"; - DataConverterPotionId.potions[6] = "minecraft:night_vision"; - DataConverterPotionId.potions[7] = null; - DataConverterPotionId.potions[8] = "minecraft:weakness"; - DataConverterPotionId.potions[9] = "minecraft:strength"; - DataConverterPotionId.potions[10] = "minecraft:slowness"; - DataConverterPotionId.potions[11] = "minecraft:leaping"; - DataConverterPotionId.potions[12] = "minecraft:harming"; - DataConverterPotionId.potions[13] = "minecraft:water_breathing"; - DataConverterPotionId.potions[14] = "minecraft:invisibility"; - DataConverterPotionId.potions[15] = null; - DataConverterPotionId.potions[16] = "minecraft:awkward"; - DataConverterPotionId.potions[17] = "minecraft:regeneration"; - DataConverterPotionId.potions[18] = "minecraft:swiftness"; - DataConverterPotionId.potions[19] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[20] = "minecraft:poison"; - DataConverterPotionId.potions[21] = "minecraft:healing"; - DataConverterPotionId.potions[22] = "minecraft:night_vision"; - DataConverterPotionId.potions[23] = null; - DataConverterPotionId.potions[24] = "minecraft:weakness"; - DataConverterPotionId.potions[25] = "minecraft:strength"; - DataConverterPotionId.potions[26] = "minecraft:slowness"; - DataConverterPotionId.potions[27] = "minecraft:leaping"; - DataConverterPotionId.potions[28] = "minecraft:harming"; - DataConverterPotionId.potions[29] = "minecraft:water_breathing"; - DataConverterPotionId.potions[30] = "minecraft:invisibility"; - DataConverterPotionId.potions[31] = null; - DataConverterPotionId.potions[32] = "minecraft:thick"; - DataConverterPotionId.potions[33] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[34] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[35] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[36] = "minecraft:strong_poison"; - DataConverterPotionId.potions[37] = "minecraft:strong_healing"; - DataConverterPotionId.potions[38] = "minecraft:night_vision"; - DataConverterPotionId.potions[39] = null; - DataConverterPotionId.potions[40] = "minecraft:weakness"; - DataConverterPotionId.potions[41] = "minecraft:strong_strength"; - DataConverterPotionId.potions[42] = "minecraft:slowness"; - DataConverterPotionId.potions[43] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[44] = "minecraft:strong_harming"; - DataConverterPotionId.potions[45] = "minecraft:water_breathing"; - DataConverterPotionId.potions[46] = "minecraft:invisibility"; - DataConverterPotionId.potions[47] = null; - DataConverterPotionId.potions[48] = null; - DataConverterPotionId.potions[49] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[50] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[51] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[52] = "minecraft:strong_poison"; - DataConverterPotionId.potions[53] = "minecraft:strong_healing"; - DataConverterPotionId.potions[54] = "minecraft:night_vision"; - DataConverterPotionId.potions[55] = null; - DataConverterPotionId.potions[56] = "minecraft:weakness"; - DataConverterPotionId.potions[57] = "minecraft:strong_strength"; - DataConverterPotionId.potions[58] = "minecraft:slowness"; - DataConverterPotionId.potions[59] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[60] = "minecraft:strong_harming"; - DataConverterPotionId.potions[61] = "minecraft:water_breathing"; - DataConverterPotionId.potions[62] = "minecraft:invisibility"; - DataConverterPotionId.potions[63] = null; - DataConverterPotionId.potions[64] = "minecraft:mundane"; - DataConverterPotionId.potions[65] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[66] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[67] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[68] = "minecraft:long_poison"; - DataConverterPotionId.potions[69] = "minecraft:healing"; - DataConverterPotionId.potions[70] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[71] = null; - DataConverterPotionId.potions[72] = "minecraft:long_weakness"; - DataConverterPotionId.potions[73] = "minecraft:long_strength"; - DataConverterPotionId.potions[74] = "minecraft:long_slowness"; - DataConverterPotionId.potions[75] = "minecraft:long_leaping"; - DataConverterPotionId.potions[76] = "minecraft:harming"; - DataConverterPotionId.potions[77] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[78] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[79] = null; - DataConverterPotionId.potions[80] = "minecraft:awkward"; - DataConverterPotionId.potions[81] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[82] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[83] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[84] = "minecraft:long_poison"; - DataConverterPotionId.potions[85] = "minecraft:healing"; - DataConverterPotionId.potions[86] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[87] = null; - DataConverterPotionId.potions[88] = "minecraft:long_weakness"; - DataConverterPotionId.potions[89] = "minecraft:long_strength"; - DataConverterPotionId.potions[90] = "minecraft:long_slowness"; - DataConverterPotionId.potions[91] = "minecraft:long_leaping"; - DataConverterPotionId.potions[92] = "minecraft:harming"; - DataConverterPotionId.potions[93] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[94] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[95] = null; - DataConverterPotionId.potions[96] = "minecraft:thick"; - DataConverterPotionId.potions[97] = "minecraft:regeneration"; - DataConverterPotionId.potions[98] = "minecraft:swiftness"; - DataConverterPotionId.potions[99] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[100] = "minecraft:poison"; - DataConverterPotionId.potions[101] = "minecraft:strong_healing"; - DataConverterPotionId.potions[102] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[103] = null; - DataConverterPotionId.potions[104] = "minecraft:long_weakness"; - DataConverterPotionId.potions[105] = "minecraft:strength"; - DataConverterPotionId.potions[106] = "minecraft:long_slowness"; - DataConverterPotionId.potions[107] = "minecraft:leaping"; - DataConverterPotionId.potions[108] = "minecraft:strong_harming"; - DataConverterPotionId.potions[109] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[110] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[111] = null; - DataConverterPotionId.potions[112] = null; - DataConverterPotionId.potions[113] = "minecraft:regeneration"; - DataConverterPotionId.potions[114] = "minecraft:swiftness"; - DataConverterPotionId.potions[115] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[116] = "minecraft:poison"; - DataConverterPotionId.potions[117] = "minecraft:strong_healing"; - DataConverterPotionId.potions[118] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[119] = null; - DataConverterPotionId.potions[120] = "minecraft:long_weakness"; - DataConverterPotionId.potions[121] = "minecraft:strength"; - DataConverterPotionId.potions[122] = "minecraft:long_slowness"; - DataConverterPotionId.potions[123] = "minecraft:leaping"; - DataConverterPotionId.potions[124] = "minecraft:strong_harming"; - DataConverterPotionId.potions[125] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[126] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[127] = null; - } - } - - private static class DataConverterSpawnEgg implements DataConverter { - - private static final String[] eggs = new String[256]; - - DataConverterSpawnEgg() { - } - - public int getDataVersion() { - return 105; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); - short short0 = cmp.getShort("Damage"); - - if (!nbttagcompound2.contains("id", 8)) { - String s = DataConverterSpawnEgg.eggs[short0 & 255]; - - if (s != null) { - nbttagcompound2.putString("id", s); - nbttagcompound1.put("EntityTag", nbttagcompound2); - cmp.put("tag", nbttagcompound1); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - - static { - - DataConverterSpawnEgg.eggs[1] = "Item"; - DataConverterSpawnEgg.eggs[2] = "XPOrb"; - DataConverterSpawnEgg.eggs[7] = "ThrownEgg"; - DataConverterSpawnEgg.eggs[8] = "LeashKnot"; - DataConverterSpawnEgg.eggs[9] = "Painting"; - DataConverterSpawnEgg.eggs[10] = "Arrow"; - DataConverterSpawnEgg.eggs[11] = "Snowball"; - DataConverterSpawnEgg.eggs[12] = "Fireball"; - DataConverterSpawnEgg.eggs[13] = "SmallFireball"; - DataConverterSpawnEgg.eggs[14] = "ThrownEnderpearl"; - DataConverterSpawnEgg.eggs[15] = "EyeOfEnderSignal"; - DataConverterSpawnEgg.eggs[16] = "ThrownPotion"; - DataConverterSpawnEgg.eggs[17] = "ThrownExpBottle"; - DataConverterSpawnEgg.eggs[18] = "ItemFrame"; - DataConverterSpawnEgg.eggs[19] = "WitherSkull"; - DataConverterSpawnEgg.eggs[20] = "PrimedTnt"; - DataConverterSpawnEgg.eggs[21] = "FallingSand"; - DataConverterSpawnEgg.eggs[22] = "FireworksRocketEntity"; - DataConverterSpawnEgg.eggs[23] = "TippedArrow"; - DataConverterSpawnEgg.eggs[24] = "SpectralArrow"; - DataConverterSpawnEgg.eggs[25] = "ShulkerBullet"; - DataConverterSpawnEgg.eggs[26] = "DragonFireball"; - DataConverterSpawnEgg.eggs[30] = "ArmorStand"; - DataConverterSpawnEgg.eggs[41] = "Boat"; - DataConverterSpawnEgg.eggs[42] = "MinecartRideable"; - DataConverterSpawnEgg.eggs[43] = "MinecartChest"; - DataConverterSpawnEgg.eggs[44] = "MinecartFurnace"; - DataConverterSpawnEgg.eggs[45] = "MinecartTNT"; - DataConverterSpawnEgg.eggs[46] = "MinecartHopper"; - DataConverterSpawnEgg.eggs[47] = "MinecartSpawner"; - DataConverterSpawnEgg.eggs[40] = "MinecartCommandBlock"; - DataConverterSpawnEgg.eggs[48] = "Mob"; - DataConverterSpawnEgg.eggs[49] = "Monster"; - DataConverterSpawnEgg.eggs[50] = "Creeper"; - DataConverterSpawnEgg.eggs[51] = "Skeleton"; - DataConverterSpawnEgg.eggs[52] = "Spider"; - DataConverterSpawnEgg.eggs[53] = "Giant"; - DataConverterSpawnEgg.eggs[54] = "Zombie"; - DataConverterSpawnEgg.eggs[55] = "Slime"; - DataConverterSpawnEgg.eggs[56] = "Ghast"; - DataConverterSpawnEgg.eggs[57] = "PigZombie"; - DataConverterSpawnEgg.eggs[58] = "Enderman"; - DataConverterSpawnEgg.eggs[59] = "CaveSpider"; - DataConverterSpawnEgg.eggs[60] = "Silverfish"; - DataConverterSpawnEgg.eggs[61] = "Blaze"; - DataConverterSpawnEgg.eggs[62] = "LavaSlime"; - DataConverterSpawnEgg.eggs[63] = "EnderDragon"; - DataConverterSpawnEgg.eggs[64] = "WitherBoss"; - DataConverterSpawnEgg.eggs[65] = "Bat"; - DataConverterSpawnEgg.eggs[66] = "Witch"; - DataConverterSpawnEgg.eggs[67] = "Endermite"; - DataConverterSpawnEgg.eggs[68] = "Guardian"; - DataConverterSpawnEgg.eggs[69] = "Shulker"; - DataConverterSpawnEgg.eggs[90] = "Pig"; - DataConverterSpawnEgg.eggs[91] = "Sheep"; - DataConverterSpawnEgg.eggs[92] = "Cow"; - DataConverterSpawnEgg.eggs[93] = "Chicken"; - DataConverterSpawnEgg.eggs[94] = "Squid"; - DataConverterSpawnEgg.eggs[95] = "Wolf"; - DataConverterSpawnEgg.eggs[96] = "MushroomCow"; - DataConverterSpawnEgg.eggs[97] = "SnowMan"; - DataConverterSpawnEgg.eggs[98] = "Ozelot"; - DataConverterSpawnEgg.eggs[99] = "VillagerGolem"; - DataConverterSpawnEgg.eggs[100] = "EntityHorse"; - DataConverterSpawnEgg.eggs[101] = "Rabbit"; - DataConverterSpawnEgg.eggs[120] = "Villager"; - DataConverterSpawnEgg.eggs[200] = "EnderCrystal"; - } - } - - private static class DataConverterMinecart implements DataConverter { - - private static final List a = Lists.newArrayList( - "MinecartRideable", - "MinecartChest", - "MinecartFurnace", - "MinecartTNT", - "MinecartSpawner", - "MinecartHopper", - "MinecartCommandBlock" - ); - - DataConverterMinecart() { - } - - public int getDataVersion() { - return 106; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Minecart".equals(cmp.getString("id"))) { - String s = "MinecartRideable"; - int i = cmp.getInt("Type"); - - if (i > 0 && i < DataConverterMinecart.a.size()) { - s = DataConverterMinecart.a.get(i); - } - - cmp.putString("id", s); - cmp.remove("Type"); - } - - return cmp; - } - - } - - private static class DataConverterMobSpawner implements DataConverter { - - DataConverterMobSpawner() { - } - - public int getDataVersion() { - return 107; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (!"MobSpawner".equals(cmp.getString("id"))) { - return cmp; - } else { - if (cmp.contains("EntityId", 8)) { - String s = cmp.getString("EntityId"); - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); - - nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); - cmp.put("SpawnData", nbttagcompound1); - cmp.remove("EntityId"); - } - - if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); - - for (int i = 0; i < nbttaglist.size(); ++i) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); - - if (nbttagcompound2.contains("Type", 8)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); - - nbttagcompound3.putString("id", nbttagcompound2.getString("Type")); - nbttagcompound2.put("Entity", nbttagcompound3); - nbttagcompound2.remove("Type"); - nbttagcompound2.remove("Properties"); - } - } - } - - return cmp; - } - } - - } - - private static class DataConverterUUID implements DataConverter { - - DataConverterUUID() { - } - - public int getDataVersion() { - return 108; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("UUID", 8)) { - cmp.putUUID("UUID", UUID.fromString(cmp.getString("UUID"))); - } - - return cmp; - } - - } - - private static class DataConverterHealth implements DataConverter { - - private static final Set a = Sets.newHashSet( - "ArmorStand", - "Bat", - "Blaze", - "CaveSpider", - "Chicken", - "Cow", - "Creeper", - "EnderDragon", - "Enderman", - "Endermite", - "EntityHorse", - "Ghast", - "Giant", - "Guardian", - "LavaSlime", - "MushroomCow", - "Ozelot", - "Pig", - "PigZombie", - "Rabbit", - "Sheep", - "Shulker", - "Silverfish", - "Skeleton", - "Slime", - "SnowMan", - "Spider", - "Squid", - "Villager", - "VillagerGolem", - "Witch", - "WitherBoss", - "Wolf", - "Zombie" - ); - - DataConverterHealth() { - } - - public int getDataVersion() { - return 109; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (DataConverterHealth.a.contains(cmp.getString("id"))) { - float f; - - if (cmp.contains("HealF", 99)) { - f = cmp.getFloat("HealF"); - cmp.remove("HealF"); - } else { - if (!cmp.contains("Health", 99)) { - return cmp; - } - - f = cmp.getFloat("Health"); - } - - cmp.putFloat("Health", f); - } - - return cmp; - } - - } - - private static class DataConverterSaddle implements DataConverter { - - DataConverterSaddle() { - } - - public int getDataVersion() { - return 110; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id")) && !cmp.contains("SaddleItem", 10) && cmp.getBoolean("Saddle")) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound1.putString("id", "minecraft:saddle"); - nbttagcompound1.putByte("Count", (byte) 1); - nbttagcompound1.putShort("Damage", (short) 0); - cmp.put("SaddleItem", nbttagcompound1); - cmp.remove("Saddle"); - } - - return cmp; - } - - } - - private static class DataConverterHanging implements DataConverter { - - DataConverterHanging() { - } - - public int getDataVersion() { - return 111; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - boolean flag = "Painting".equals(s); - boolean flag1 = "ItemFrame".equals(s); - - if ((flag || flag1) && !cmp.contains("Facing", 99)) { - Direction enumdirection; - - if (cmp.contains("Direction", 99)) { - enumdirection = Direction.from2DDataValue(cmp.getByte("Direction")); - cmp.putInt("TileX", cmp.getInt("TileX") + enumdirection.getStepX()); - cmp.putInt("TileY", cmp.getInt("TileY") + enumdirection.getStepY()); - cmp.putInt("TileZ", cmp.getInt("TileZ") + enumdirection.getStepZ()); - cmp.remove("Direction"); - if (flag1 && cmp.contains("ItemRotation", 99)) { - cmp.putByte("ItemRotation", (byte) (cmp.getByte("ItemRotation") * 2)); - } - } else { - enumdirection = Direction.from2DDataValue(cmp.getByte("Dir")); - cmp.remove("Dir"); - } - - cmp.putByte("Facing", (byte) enumdirection.get2DDataValue()); - } - - return cmp; - } - - } - - private static class DataConverterDropChances implements DataConverter { - - DataConverterDropChances() { - } - - public int getDataVersion() { - return 113; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist; - - if (cmp.contains("HandDropChances", 9)) { - nbttaglist = cmp.getList("HandDropChances", 5); - if (nbttaglist.size() == 2 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F) { - cmp.remove("HandDropChances"); - } - } - - if (cmp.contains("ArmorDropChances", 9)) { - nbttaglist = cmp.getList("ArmorDropChances", 5); - if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat( - 2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { - cmp.remove("ArmorDropChances"); - } - } - - return cmp; - } - - } - - private static class DataConverterRiding implements DataConverter { - - DataConverterRiding() { - } - - public int getDataVersion() { - return 135; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - while (cmp.contains("Riding", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = this.b(cmp); - - this.convert(cmp, nbttagcompound1); - cmp = nbttagcompound1; - } - - return cmp; - } - - protected void convert(net.minecraft.nbt.CompoundTag nbttagcompound, net.minecraft.nbt.CompoundTag nbttagcompound1) { - net.minecraft.nbt.ListTag nbttaglist = new net.minecraft.nbt.ListTag(); - - nbttaglist.add(nbttagcompound); - nbttagcompound1.put("Passengers", nbttaglist); - } - - protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagcompound) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); - - nbttagcompound.remove("Riding"); - return nbttagcompound1; - } - - } - - private static class DataConverterBook implements DataConverter { - - DataConverterBook() { - } - - public int getDataVersion() { - return 165; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:written_book".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("pages", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("pages", 8); - - for (int i = 0; i < nbttaglist.size(); ++i) { - String s = nbttaglist.getString(i); - Component object = null; - - if (!"null".equals(s) && !StringUtil.isNullOrEmpty(s)) { - if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) { - object = new TextComponent(s); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); - if (object == null) { - object = new TextComponent(""); - } - } catch (JsonParseException jsonparseexception) { - ; - } - - if (object == null) { - try { - object = Component.Serializer.fromJson(s); - } catch (JsonParseException jsonparseexception1) { - ; - } - } - - if (object == null) { - try { - object = Component.Serializer.fromJsonLenient(s); - } catch (JsonParseException jsonparseexception2) { - ; - } - } - - if (object == null) { - object = new TextComponent(s); - } - } - } else { - object = new TextComponent(""); - } - - nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); - } - - nbttagcompound1.put("pages", nbttaglist); - } - } - - return cmp; - } - - } - - private static class DataConverterCookedFish implements DataConverter { - - private static final ResourceLocation a = new ResourceLocation("cooked_fished"); - - DataConverterCookedFish() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(new ResourceLocation(cmp.getString("id")))) { - cmp.putString("id", "minecraft:cooked_fish"); - } - - return cmp; - } - - } - - private static class DataConverterZombie implements DataConverter { - - private static final Random a = new Random(); - - DataConverterZombie() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id")) && cmp.getBoolean("IsVillager")) { - if (!cmp.contains("ZombieType", 99)) { - int i = -1; - - if (cmp.contains("VillagerProfession", 99)) { - try { - i = this.convert(cmp.getInt("VillagerProfession")); - } catch (RuntimeException runtimeexception) { - ; - } - } - - if (i == -1) { - i = this.convert(DataConverterZombie.a.nextInt(6)); - } - - cmp.putInt("ZombieType", i); - } - - cmp.remove("IsVillager"); - } - - return cmp; - } - - private int convert(int i) { - return i >= 0 && i < 6 ? i : -1; - } - - } - - private static class DataConverterVBO implements DataConverter { - - DataConverterVBO() { - } - - public int getDataVersion() { - return 505; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.putString("useVbo", "true"); - return cmp; - } - - } - - private static class DataConverterGuardian implements DataConverter { - - DataConverterGuardian() { - } - - public int getDataVersion() { - return 700; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Guardian".equals(cmp.getString("id"))) { - if (cmp.getBoolean("Elder")) { - cmp.putString("id", "ElderGuardian"); - } - - cmp.remove("Elder"); - } - - return cmp; - } - - } - - private static class DataConverterSkeleton implements DataConverter { - - DataConverterSkeleton() { - } - - public int getDataVersion() { - return 701; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - - if ("Skeleton".equals(s)) { - int i = cmp.getInt("SkeletonType"); - - if (i == 1) { - cmp.putString("id", "WitherSkeleton"); - } else if (i == 2) { - cmp.putString("id", "Stray"); - } - - cmp.remove("SkeletonType"); - } - - return cmp; - } - - } - - private static class DataConverterZombieType implements DataConverter { - - DataConverterZombieType() { - } - - public int getDataVersion() { - return 702; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id"))) { - int i = cmp.getInt("ZombieType"); - - switch (i) { - case 0: - default: - break; - - case 1: - case 2: - case 3: - case 4: - case 5: - cmp.putString("id", "ZombieVillager"); - cmp.putInt("Profession", i - 1); - break; - - case 6: - cmp.putString("id", "Husk"); - } - - cmp.remove("ZombieType"); - } - - return cmp; - } - - } - - private static class DataConverterHorse implements DataConverter { - - DataConverterHorse() { - } - - public int getDataVersion() { - return 703; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id"))) { - int i = cmp.getInt("Type"); - - switch (i) { - case 0: - default: - cmp.putString("id", "Horse"); - break; - - case 1: - cmp.putString("id", "Donkey"); - break; - - case 2: - cmp.putString("id", "Mule"); - break; - - case 3: - cmp.putString("id", "ZombieHorse"); - break; - - case 4: - cmp.putString("id", "SkeletonHorse"); - } - - cmp.remove("Type"); - } - - return cmp; - } - - } - - private static class DataConverterTileEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - DataConverterTileEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterTileEntity.a.get(cmp.getString("id")); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - - static { - DataConverterTileEntity.a.put("Airportal", "minecraft:end_portal"); - DataConverterTileEntity.a.put("Banner", "minecraft:banner"); - DataConverterTileEntity.a.put("Beacon", "minecraft:beacon"); - DataConverterTileEntity.a.put("Cauldron", "minecraft:brewing_stand"); - DataConverterTileEntity.a.put("Chest", "minecraft:chest"); - DataConverterTileEntity.a.put("Comparator", "minecraft:comparator"); - DataConverterTileEntity.a.put("Control", "minecraft:command_block"); - DataConverterTileEntity.a.put("DLDetector", "minecraft:daylight_detector"); - DataConverterTileEntity.a.put("Dropper", "minecraft:dropper"); - DataConverterTileEntity.a.put("EnchantTable", "minecraft:enchanting_table"); - DataConverterTileEntity.a.put("EndGateway", "minecraft:end_gateway"); - DataConverterTileEntity.a.put("EnderChest", "minecraft:ender_chest"); - DataConverterTileEntity.a.put("FlowerPot", "minecraft:flower_pot"); - DataConverterTileEntity.a.put("Furnace", "minecraft:furnace"); - DataConverterTileEntity.a.put("Hopper", "minecraft:hopper"); - DataConverterTileEntity.a.put("MobSpawner", "minecraft:mob_spawner"); - DataConverterTileEntity.a.put("Music", "minecraft:noteblock"); - DataConverterTileEntity.a.put("Piston", "minecraft:piston"); - DataConverterTileEntity.a.put("RecordPlayer", "minecraft:jukebox"); - DataConverterTileEntity.a.put("Sign", "minecraft:sign"); - DataConverterTileEntity.a.put("Skull", "minecraft:skull"); - DataConverterTileEntity.a.put("Structure", "minecraft:structure_block"); - DataConverterTileEntity.a.put("Trap", "minecraft:dispenser"); - } - } - - private static class DataConverterEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - DataConverterEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterEntity.a.get(cmp.getString("id")); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - - static { - DataConverterEntity.a.put("AreaEffectCloud", "minecraft:area_effect_cloud"); - DataConverterEntity.a.put("ArmorStand", "minecraft:armor_stand"); - DataConverterEntity.a.put("Arrow", "minecraft:arrow"); - DataConverterEntity.a.put("Bat", "minecraft:bat"); - DataConverterEntity.a.put("Blaze", "minecraft:blaze"); - DataConverterEntity.a.put("Boat", "minecraft:boat"); - DataConverterEntity.a.put("CaveSpider", "minecraft:cave_spider"); - DataConverterEntity.a.put("Chicken", "minecraft:chicken"); - DataConverterEntity.a.put("Cow", "minecraft:cow"); - DataConverterEntity.a.put("Creeper", "minecraft:creeper"); - DataConverterEntity.a.put("Donkey", "minecraft:donkey"); - DataConverterEntity.a.put("DragonFireball", "minecraft:dragon_fireball"); - DataConverterEntity.a.put("ElderGuardian", "minecraft:elder_guardian"); - DataConverterEntity.a.put("EnderCrystal", "minecraft:ender_crystal"); - DataConverterEntity.a.put("EnderDragon", "minecraft:ender_dragon"); - DataConverterEntity.a.put("Enderman", "minecraft:enderman"); - DataConverterEntity.a.put("Endermite", "minecraft:endermite"); - DataConverterEntity.a.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal"); - DataConverterEntity.a.put("FallingSand", "minecraft:falling_block"); - DataConverterEntity.a.put("Fireball", "minecraft:fireball"); - DataConverterEntity.a.put("FireworksRocketEntity", "minecraft:fireworks_rocket"); - DataConverterEntity.a.put("Ghast", "minecraft:ghast"); - DataConverterEntity.a.put("Giant", "minecraft:giant"); - DataConverterEntity.a.put("Guardian", "minecraft:guardian"); - DataConverterEntity.a.put("Horse", "minecraft:horse"); - DataConverterEntity.a.put("Husk", "minecraft:husk"); - DataConverterEntity.a.put("Item", "minecraft:item"); - DataConverterEntity.a.put("ItemFrame", "minecraft:item_frame"); - DataConverterEntity.a.put("LavaSlime", "minecraft:magma_cube"); - DataConverterEntity.a.put("LeashKnot", "minecraft:leash_knot"); - DataConverterEntity.a.put("MinecartChest", "minecraft:chest_minecart"); - DataConverterEntity.a.put("MinecartCommandBlock", "minecraft:commandblock_minecart"); - DataConverterEntity.a.put("MinecartFurnace", "minecraft:furnace_minecart"); - DataConverterEntity.a.put("MinecartHopper", "minecraft:hopper_minecart"); - DataConverterEntity.a.put("MinecartRideable", "minecraft:minecart"); - DataConverterEntity.a.put("MinecartSpawner", "minecraft:spawner_minecart"); - DataConverterEntity.a.put("MinecartTNT", "minecraft:tnt_minecart"); - DataConverterEntity.a.put("Mule", "minecraft:mule"); - DataConverterEntity.a.put("MushroomCow", "minecraft:mooshroom"); - DataConverterEntity.a.put("Ozelot", "minecraft:ocelot"); - DataConverterEntity.a.put("Painting", "minecraft:painting"); - DataConverterEntity.a.put("Pig", "minecraft:pig"); - DataConverterEntity.a.put("PigZombie", "minecraft:zombie_pigman"); - DataConverterEntity.a.put("PolarBear", "minecraft:polar_bear"); - DataConverterEntity.a.put("PrimedTnt", "minecraft:tnt"); - DataConverterEntity.a.put("Rabbit", "minecraft:rabbit"); - DataConverterEntity.a.put("Sheep", "minecraft:sheep"); - DataConverterEntity.a.put("Shulker", "minecraft:shulker"); - DataConverterEntity.a.put("ShulkerBullet", "minecraft:shulker_bullet"); - DataConverterEntity.a.put("Silverfish", "minecraft:silverfish"); - DataConverterEntity.a.put("Skeleton", "minecraft:skeleton"); - DataConverterEntity.a.put("SkeletonHorse", "minecraft:skeleton_horse"); - DataConverterEntity.a.put("Slime", "minecraft:slime"); - DataConverterEntity.a.put("SmallFireball", "minecraft:small_fireball"); - DataConverterEntity.a.put("SnowMan", "minecraft:snowman"); - DataConverterEntity.a.put("Snowball", "minecraft:snowball"); - DataConverterEntity.a.put("SpectralArrow", "minecraft:spectral_arrow"); - DataConverterEntity.a.put("Spider", "minecraft:spider"); - DataConverterEntity.a.put("Squid", "minecraft:squid"); - DataConverterEntity.a.put("Stray", "minecraft:stray"); - DataConverterEntity.a.put("ThrownEgg", "minecraft:egg"); - DataConverterEntity.a.put("ThrownEnderpearl", "minecraft:ender_pearl"); - DataConverterEntity.a.put("ThrownExpBottle", "minecraft:xp_bottle"); - DataConverterEntity.a.put("ThrownPotion", "minecraft:potion"); - DataConverterEntity.a.put("Villager", "minecraft:villager"); - DataConverterEntity.a.put("VillagerGolem", "minecraft:villager_golem"); - DataConverterEntity.a.put("Witch", "minecraft:witch"); - DataConverterEntity.a.put("WitherBoss", "minecraft:wither"); - DataConverterEntity.a.put("WitherSkeleton", "minecraft:wither_skeleton"); - DataConverterEntity.a.put("WitherSkull", "minecraft:wither_skull"); - DataConverterEntity.a.put("Wolf", "minecraft:wolf"); - DataConverterEntity.a.put("XPOrb", "minecraft:xp_orb"); - DataConverterEntity.a.put("Zombie", "minecraft:zombie"); - DataConverterEntity.a.put("ZombieHorse", "minecraft:zombie_horse"); - DataConverterEntity.a.put("ZombieVillager", "minecraft:zombie_villager"); - } - } - - private static class DataConverterPotionWater implements DataConverter { - - DataConverterPotionWater() { - } - - public int getDataVersion() { - return 806; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - - if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals( - s)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (!nbttagcompound1.contains("Potion", 8)) { - nbttagcompound1.putString("Potion", "minecraft:water"); - } - - if (!cmp.contains("tag", 10)) { - cmp.put("tag", nbttagcompound1); - } - } - - return cmp; - } - - } - - private static class DataConverterShulker implements DataConverter { - - DataConverterShulker() { - } - - public int getDataVersion() { - return 808; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id")) && !cmp.contains("Color", 99)) { - cmp.putByte("Color", (byte) 10); - } - - return cmp; - } - - } - - private static class DataConverterShulkerBoxItem implements DataConverter { - - public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"}; - - DataConverterShulkerBoxItem() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker_box".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - - if (nbttagcompound2.getList("Items", 10).isEmpty()) { - nbttagcompound2.remove("Items"); - } - - int i = nbttagcompound2.getInt("Color"); - - nbttagcompound2.remove("Color"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - - cmp.putString("id", DataConverterShulkerBoxItem.a[i % 16]); - } - } - - return cmp; - } - - } - - private static class DataConverterShulkerBoxBlock implements DataConverter { - - DataConverterShulkerBoxBlock() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id"))) { - cmp.remove("Color"); - } - - return cmp; - } - - } - - private static class DataConverterLang implements DataConverter { - - DataConverterLang() { - } - - public int getDataVersion() { - return 816; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("lang", 8)) { - cmp.putString("lang", cmp.getString("lang").toLowerCase(Locale.ROOT)); - } - - return cmp; - } - - } - - private static class DataConverterTotem implements DataConverter { - - DataConverterTotem() { - } - - public int getDataVersion() { - return 820; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:totem".equals(cmp.getString("id"))) { - cmp.putString("id", "minecraft:totem_of_undying"); - } - - return cmp; - } - - } - - private static class DataConverterBedBlock implements DataConverter { - - private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); - - DataConverterBedBlock() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - try { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); - int i = nbttagcompound1.getInt("xPos"); - int j = nbttagcompound1.getInt("zPos"); - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("TileEntities", 10); - net.minecraft.nbt.ListTag nbttaglist1 = nbttagcompound1.getList("Sections", 10); - - for (int k = 0; k < nbttaglist1.size(); ++k) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); - byte b0 = nbttagcompound2.getByte("Y"); - byte[] abyte = nbttagcompound2.getByteArray("Blocks"); - - for (int l = 0; l < abyte.length; ++l) { - if (416 == (abyte[l] & 255) << 4) { - int i1 = l & 15; - int j1 = l >> 8 & 15; - int k1 = l >> 4 & 15; - net.minecraft.nbt.CompoundTag nbttagcompound3 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound3.putString("id", "bed"); - nbttagcompound3.putInt("x", i1 + (i << 4)); - nbttagcompound3.putInt("y", j1 + (b0 << 4)); - nbttagcompound3.putInt("z", k1 + (j << 4)); - nbttaglist.add(nbttagcompound3); - } - } - } - } catch (Exception exception) { - DataConverterBedBlock.a.warn("Unable to datafix Bed blocks, level format may be missing tags."); - } - - return cmp; - } - - } - - private static class DataConverterBedItem implements DataConverter { - - DataConverterBedItem() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:bed".equals(cmp.getString("id")) && cmp.getShort("Damage") == 0) { - cmp.putShort("Damage", (short) DyeColor.RED.getId()); - } - - return cmp; - } - - } - - private static class DataConverterSignText implements DataConverter { - - public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { - MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws - JsonParseException { - if (jsonelement.isJsonPrimitive()) { - return new TextComponent(jsonelement.getAsString()); - } else if (jsonelement.isJsonArray()) { - JsonArray jsonarray = jsonelement.getAsJsonArray(); - MutableComponent ichatbasecomponent = null; - Iterator iterator = jsonarray.iterator(); - - while (iterator.hasNext()) { - JsonElement jsonelement1 = (JsonElement) iterator.next(); - MutableComponent ichatbasecomponent1 = this.a( - jsonelement1, - jsonelement1.getClass(), - jsondeserializationcontext - ); - - if (ichatbasecomponent == null) { - ichatbasecomponent = ichatbasecomponent1; - } else { - ichatbasecomponent.append(ichatbasecomponent1); - } - } - - return ichatbasecomponent; - } else { - throw new JsonParseException("Don't know how to turn " + jsonelement + " into a Component"); - } - } - - public Object deserialize( - JsonElement jsonelement, - Type type, - JsonDeserializationContext jsondeserializationcontext - ) throws JsonParseException { - return this.a(jsonelement, type, jsondeserializationcontext); - } - }).create(); - - DataConverterSignText() { - } - - public int getDataVersion() { - return 101; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Sign".equals(cmp.getString("id"))) { - this.convert(cmp, "Text1"); - this.convert(cmp, "Text2"); - this.convert(cmp, "Text3"); - this.convert(cmp, "Text4"); - } - - return cmp; - } - - private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { - String s1 = nbttagcompound.getString(s); - Component object = null; - - if (!"null".equals(s1) && !StringUtil.isNullOrEmpty(s1)) { - if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) { - object = new TextComponent(s1); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); - if (object == null) { - object = new TextComponent(""); - } - } catch (JsonParseException jsonparseexception) { - ; - } - - if (object == null) { - try { - object = Component.Serializer.fromJson(s1); - } catch (JsonParseException jsonparseexception1) { - ; - } - } - - if (object == null) { - try { - object = Component.Serializer.fromJsonLenient(s1); - } catch (JsonParseException jsonparseexception2) { - ; - } - } - - if (object == null) { - object = new TextComponent(s1); - } - } - } else { - object = new TextComponent(""); - } - - nbttagcompound.putString(s, Component.Serializer.toJson(object)); - } - - } - - private static class DataInspectorPlayerVehicle implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("RootVehicle", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); - - if (nbttagcompound1.contains("Entity", 10)) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - } - - return cmp; - } - - } - - private static class DataInspectorLevelPlayer implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Player", 10)) { - convertCompound(LegacyType.PLAYER, cmp, "Player", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorStructure implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.ListTag nbttaglist; - int j; - net.minecraft.nbt.CompoundTag nbttagcompound1; - - if (cmp.contains("entities", 9)) { - nbttaglist = cmp.getList("entities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.contains("nbt", 10)) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - } - - if (cmp.contains("blocks", 9)) { - nbttaglist = cmp.getList("blocks", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.contains("nbt", 10)) { - convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorChunks implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Level", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); - net.minecraft.nbt.ListTag nbttaglist; - int j; - - if (nbttagcompound1.contains("Entities", 9)) { - nbttaglist = nbttagcompound1.getList("Entities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert( - LegacyType.ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); - } - } - - if (nbttagcompound1.contains("TileEntities", 9)) { - nbttaglist = nbttagcompound1.getList("TileEntities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert( - LegacyType.BLOCK_ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorEntityPassengers implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Passengers", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Passengers", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ENTITY, nbttaglist.getCompound(j), sourceVer, targetVer)); - } - } - - return cmp; - } - - } - - private static class DataInspectorPlayer implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - convertItems(cmp, "Inventory", sourceVer, targetVer); - convertItems(cmp, "EnderItems", sourceVer, targetVer); - if (cmp.contains("ShoulderEntityLeft", 10)) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityLeft", sourceVer, targetVer); - } - - if (cmp.contains("ShoulderEntityRight", 10)) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityRight", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorVillagers implements DataInspector { - - ResourceLocation entityVillager = getKey("EntityVillager"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (entityVillager.equals(new ResourceLocation(cmp.getString("id"))) && cmp.contains("Offers", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Offers"); - - if (nbttagcompound1.contains("Recipes", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); - - convertItem(nbttagcompound2, "buy", sourceVer, targetVer); - convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); - convertItem(nbttagcompound2, "sell", sourceVer, targetVer); - nbttaglist.set(j, nbttagcompound2); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorMobSpawnerMinecart implements DataInspector { - - ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - String s = cmp.getString("id"); - if (entityMinecartMobSpawner.equals(new ResourceLocation(s))) { - cmp.putString("id", tileEntityMobSpawner.toString()); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", s); - } - - return cmp; - } - - } - - private static class DataInspectorMobSpawnerMobs implements DataInspector { - - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityMobSpawner.equals(new ResourceLocation(cmp.getString("id")))) { - if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); - - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - } - - convertCompound(LegacyType.ENTITY, cmp, "SpawnData", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorCommandBlock implements DataInspector { - - ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityCommand.equals(new ResourceLocation(cmp.getString("id")))) { - cmp.putString("id", "Control"); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", "MinecartCommandBlock"); - } - - return cmp; - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightFakePlayer.java deleted file mode 100644 index 9f081b05e..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightFakePlayer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe; - -import com.mojang.authlib.GameProfile; -import net.minecraft.network.chat.ChatType; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stat; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.phys.Vec3; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -import java.util.OptionalInt; -import java.util.UUID; - -class PaperweightFakePlayer extends ServerPlayer { - - private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( - UUID.nameUUIDFromBytes("worldedit".getBytes()), - "[WorldEdit]" - ); - private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); - - PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); - } - - @Override - public Vec3 position() { - return ORIGIN; - } - - @Override - public void tick() { - } - - @Override - public void die(DamageSource damagesource) { - } - - @Override - public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) { - return this; - } - - @Override - public OptionalInt openMenu(MenuProvider factory) { - return OptionalInt.empty(); - } - - @Override - public void updateOptions(ServerboundClientInformationPacket packet) { - } - - @Override - public void displayClientMessage(Component message, boolean actionBar) { - } - - @Override - public void sendMessage(Component message, ChatType type, UUID sender) { - } - - @Override - public void awardStat(Stat stat, int amount) { - } - - @Override - public void awardStat(Stat stat) { - } - - @Override - public boolean isInvulnerableTo(DamageSource damageSource) { - return true; - } - - @Override - public void openTextEdit(SignBlockEntity sign) { - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightWorldNativeAccess.java deleted file mode 100644 index 701e40b12..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightWorldNativeAccess.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe; - -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.world.block.BlockState; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; -import org.bukkit.event.block.BlockPhysicsEvent; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.util.Objects; - -public class PaperweightWorldNativeAccess implements - WorldNativeAccess { - - private static final int UPDATE = 1; - private static final int NOTIFY = 2; - - private final PaperweightAdapter adapter; - private final WeakReference world; - private SideEffectSet sideEffectSet; - - public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference world) { - this.adapter = adapter; - this.world = world; - } - - private ServerLevel getWorld() { - return Objects.requireNonNull(world.get(), "The reference to the world was lost"); - } - - @Override - public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { - this.sideEffectSet = sideEffectSet; - } - - @Override - public LevelChunk getChunk(int x, int z) { - return getWorld().getChunk(x, z); - } - - @Override - public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) { - int stateId = BlockStateIdAccess.getBlockStateId(state); - return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) { - return chunk.getBlockState(position); - } - - @Nullable - @Override - public net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState state - ) { - return chunk.setType(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState block, - BlockPos position - ) { - return Block.updateFromNeighbourShapes(block, getWorld(), position); - } - - @Override - public BlockPos getPosition(int x, int y, int z) { - return new BlockPos(x, y, z); - } - - @Override - public void updateLightingForBlock(BlockPos position) { - getWorld().getChunkSource().getLightEngine().checkBlock(position); - } - - @Override - public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) { - return false; - } - - @Override - public void notifyBlockUpdate( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); - } - } - - @Override - public boolean isChunkTicking(LevelChunk chunk) { - return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - } - - @Override - public void markBlockChanged(LevelChunk chunk, BlockPos position) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().getChunkSource().blockChanged(position); - } - } - - @Override - public void notifyNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - ServerLevel world = getWorld(); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - world.updateNeighborsAt(pos, oldState.getBlock()); - } else { - // When we don't want events, manually run the physics without them. - Block block = oldState.getBlock(); - fireNeighborChanged(pos, world, block, pos.west()); - fireNeighborChanged(pos, world, block, pos.east()); - fireNeighborChanged(pos, world, block, pos.below()); - fireNeighborChanged(pos, world, block, pos.above()); - fireNeighborChanged(pos, world, block, pos.north()); - fireNeighborChanged(pos, world, block, pos.south()); - } - if (newState.hasAnalogOutputSignal()) { - world.updateNeighbourForOutputSignal(pos, newState.getBlock()); - } - } - - private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { - world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false); - } - - @Override - public void updateNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { - ServerLevel world = getWorld(); - // a == updateNeighbors - // b == updateDiagonalNeighbors - oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - CraftWorld craftWorld = world.getWorld(); - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), - CraftBlockData.fromData(newState) - ); - world.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } - newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit); - newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); - } - - @Override - public void onBlockStateChange( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - getWorld().onBlockStateChange(pos, oldState, newState); - } - - @Override - public void flush() { - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightBlockMaterial.java deleted file mode 100644 index aac664459..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightBlockMaterial.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.util.ReflectionUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.world.registry.BlockMaterial; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.EmptyBlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.PushReaction; -import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; - -public class PaperweightBlockMaterial implements BlockMaterial { - - private final Block block; - private final BlockState blockState; - private final Material material; - private final boolean isTranslucent; - private final CraftBlockData craftBlockData; - private final org.bukkit.Material craftMaterial; - private final int opacity; - private final CompoundTag tile; - - public PaperweightBlockMaterial(Block block) { - this(block, block.defaultBlockState()); - } - - public PaperweightBlockMaterial(Block block, BlockState blockState) { - this.block = block; - this.blockState = blockState; - this.material = blockState.getMaterial(); - this.craftBlockData = CraftBlockData.fromData(blockState); - this.craftMaterial = craftBlockData.getMaterial(); - BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName( - "properties", "aP")); - this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo, - Refraction.pickName("canOcclude", "n") - ); - opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); - BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( - BlockPos.ZERO, - blockState - ); - tile = tileEntity == null - ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(() -> tileEntity.save(new net.minecraft.nbt.CompoundTag()))); - } - - public Block getBlock() { - return block; - } - - public BlockState getState() { - return blockState; - } - - public CraftBlockData getCraftBlockData() { - return craftBlockData; - } - - public Material getMaterial() { - return material; - } - - @Override - public boolean isAir() { - return blockState.isAir(); - } - - @Override - public boolean isFullCube() { - return craftMaterial.isOccluding(); - } - - @Override - public boolean isOpaque() { - return material.isSolidBlocking(); - } - - @Override - public boolean isPowerSource() { - return blockState.isSignalSource(); - } - - @Override - public boolean isLiquid() { - return material.isLiquid(); - } - - @Override - public boolean isSolid() { - return material.isSolid(); - } - - @Override - public float getHardness() { - return craftBlockData.getState().destroySpeed; - } - - @Override - public float getResistance() { - return block.getExplosionResistance(); - } - - @Override - public float getSlipperiness() { - return block.getFriction(); - } - - @Override - public int getLightValue() { - return blockState.getLightEmission(); - } - - @Override - public int getLightOpacity() { - return opacity; - } - - @Override - public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; - } - - @Override - public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; - } - - @Override - public boolean isTicksRandomly() { - return block.isRandomlyTicking(blockState); - } - - @Override - public boolean isMovementBlocker() { - return material.isSolid(); - } - - @Override - public boolean isBurnable() { - return material.isFlammable(); - } - - @Override - public boolean isToolRequired() { - // Removed in 1.16.1, this is not present in higher versions - return false; - } - - @Override - public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); - } - - @Override - public boolean isTranslucent() { - return isTranslucent; - } - - @Override - public boolean hasContainer() { - return block instanceof EntityBlock; - } - - @Override - public boolean isTile() { - return block instanceof EntityBlock; - } - - @Override - public CompoundTag getDefaultTile() { - return tile; - } - - @Override - public int getMapColor() { - // rgb field - return material.getColor().col; - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweAdapter.java deleted file mode 100644 index 64cf2c9d6..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweAdapter.java +++ /dev/null @@ -1,709 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter; -import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.entity.LazyBaseEntity; -import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; -import com.fastasyncworldedit.core.util.NbtUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.TileEntityBlock; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen.PaperweightRegen; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; -import com.sk89q.worldedit.world.RegenOptions; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.registry.BlockMaterial; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.core.WritableRegistry; -import net.minecraft.nbt.IntTag; -import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.TreeType; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_17_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_17_R1.CraftServer; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlockState; -import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey; -import org.bukkit.entity.Player; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.Set; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements - IDelegateBukkitImplAdapter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ - private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; - - public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); - } - - @Nullable - private static String getEntityId(Entity entity) { - ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); - return resourceLocation == null ? null : resourceLocation.toString(); - } - - private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { - entity.save(compoundTag); - } - - @Override - public BukkitImplAdapter getParent() { - return parent; - } - - @SuppressWarnings("unchecked") - private synchronized boolean init() { - if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) { - return false; - } - ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size - ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size - for (int i = 0; i < ibdToStateOrdinal.length; i++) { - BlockState blockState = BlockTypesCache.states[i]; - PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial(); - int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState()); - char ordinal = blockState.getOrdinalChar(); - ibdToStateOrdinal[id] = ordinal; - ordinalToIbdID[ordinal] = id; - } - Map>> properties = new HashMap<>(); - try { - for (Field field : BlockStateProperties.class.getDeclaredFields()) { - Object obj = field.get(null); - if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property state)) { - continue; - } - Property property; - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - property = new BooleanProperty( - state.getName(), - (List) ImmutableList.copyOf(state.getPossibleValues()) - ); - } else if (state instanceof DirectionProperty) { - property = new DirectionalProperty( - state.getName(), - state - .getPossibleValues() - .stream() - .map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase())) - .collect(Collectors.toList()) - ); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - property = new EnumProperty( - state.getName(), - state - .getPossibleValues() - .stream() - .map(e -> ((StringRepresentable) e).getSerializedName()) - .collect(Collectors.toList()) - ); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - property = new IntegerProperty( - state.getName(), - (List) ImmutableList.copyOf(state.getPossibleValues()) - ); - } else { - throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state - .getClass() - .getSimpleName()); - } - properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> { - if (v == null) { - v = new ArrayList<>(Collections.singletonList(property)); - } else { - v.add(property); - } - return v; - }); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } finally { - allBlockProperties = ImmutableMap.copyOf(properties); - } - initialised = true; - return true; - } - - @Override - public BlockMaterial getMaterial(BlockType blockType) { - Block block = getBlock(blockType); - return new PaperweightBlockMaterial(block); - } - - @Override - public synchronized BlockMaterial getMaterial(BlockState state) { - net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); - return new PaperweightBlockMaterial(blockState.getBlock(), blockState); - } - - public Block getBlock(BlockType blockType) { - return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); - } - - @Deprecated - @Override - public BlockState getBlock(Location location) { - Preconditions.checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - BlockState state = adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - return state; - } - - @Override - public BaseBlock getFullBlock(final Location location) { - Preconditions.checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - BlockState state = adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - if (state.getBlockType().getMaterial().hasContainer()) { - - // Read the NBT data - BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.save(new net.minecraft.nbt.CompoundTag()); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - } - } - - return state.toBaseBlock(); - } - - @Override - public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); - } - - @SuppressWarnings("rawtypes") - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { - CraftChunk craftChunk = (CraftChunk) chunk; - LevelChunk levelChunk = craftChunk.getHandle(); - Level level = levelChunk.getLevel(); - - BlockPos blockPos = new BlockPos(x, y, z); - net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - LevelChunkSection[] levelChunkSections = levelChunk.getSections(); - int y4 = y >> 4; - LevelChunkSection section = levelChunkSections[y4]; - - net.minecraft.world.level.block.state.BlockState existing; - if (section == null) { - existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); - } else { - existing = section.getBlockState(x & 15, y & 15, z & 15); - } - - levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity - - CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null; - if (compoundTag != null || existing instanceof TileEntityBlock) { - level.setBlock(blockPos, blockState, 0); - // remove tile - if (compoundTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - BlockEntity blockEntity = level.getBlockEntity(blockPos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - blockEntity.load(tag); // readTagIntoTileEntity - load data - } - } - } else { - if (existing == blockState) { - return true; - } - if (section == null) { - if (blockState.isAir()) { - return true; - } - levelChunkSections[y4] = section = new LevelChunkSection(y4 << 4); - } - levelChunk.setBlockState(blockPos, blockState, false); - } - if (update) { - level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0); - } - return true; - } - - @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); - } - - @Override - public BaseEntity getEntity(org.bukkit.entity.Entity entity) { - Preconditions.checkNotNull(entity); - - CraftEntity craftEntity = ((CraftEntity) entity); - Entity mcEntity = craftEntity.getHandle(); - - String id = getEntityId(mcEntity); - - if (id != null) { - EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { - final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); - //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); - }; - return new LazyBaseEntity(type, saveTag); - } else { - return null; - } - } - - @Override - public Component getRichBlockName(BlockType blockType) { - return parent.getRichBlockName(blockType); - } - - @Override - public Component getRichItemName(ItemType itemType) { - return parent.getRichItemName(itemType); - } - - @Override - public Component getRichItemName(BaseItemStack itemStack) { - return parent.getRichItemName(itemStack); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockState state) { - PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); - net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState(); - return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState)); - } - - @Override - public BlockState adapt(BlockData blockData) { - CraftBlockData cbd = ((CraftBlockData) blockData); - net.minecraft.world.level.block.state.BlockState ibd = cbd.getState(); - return adapt(ibd); - } - - public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { - return BlockTypesCache.states[adaptToChar(blockState)]; - } - - public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) { - int id = Block.BLOCK_STATE_REGISTRY.getId(blockState); - if (initialised) { - return ibdToStateOrdinal[id]; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - try { - init(); - return ibdToStateOrdinal[id]; - } catch (ArrayIndexOutOfBoundsException e1) { - LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!", - blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1 - ); - return BlockTypesCache.ReservedIDs.AIR; - } - } - } - - public char ibdIDToOrdinal(int id) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - init(); - return ibdToStateOrdinal[id]; - } - } - - @Override - public char[] getIbdToStateOrdinal() { - if (initialised) { - return ibdToStateOrdinal; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal; - } - init(); - return ibdToStateOrdinal; - } - } - - public int ordinalToIbdID(char ordinal) { - if (initialised) { - return ordinalToIbdID[ordinal]; - } - synchronized (this) { - if (initialised) { - return ordinalToIbdID[ordinal]; - } - init(); - return ordinalToIbdID[ordinal]; - } - } - - @Override - public int[] getOrdinalToIbdID() { - if (initialised) { - return ordinalToIbdID; - } - synchronized (this) { - if (initialised) { - return ordinalToIbdID; - } - init(); - return ordinalToIbdID; - } - } - - @Override - public > BlockData adapt(B state) { - PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); - return material.getCraftBlockData(); - } - - @Override - public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); - ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); - if (map != null && map.wasAccessibleSinceLastSave()) { - boolean flag = false; - // PlayerChunk.d players = map.players; - Stream stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) - */ Stream.empty(); - - ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle(); - stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer) - .forEach(entityPlayer -> { - synchronized (chunkPacket) { - ClientboundLevelChunkPacket nmsPacket = (ClientboundLevelChunkPacket) chunkPacket.getNativePacket(); - if (nmsPacket == null) { - nmsPacket = mapUtil.create(this, chunkPacket); - chunkPacket.setNativePacket(nmsPacket); - } - try { - FaweCache.INSTANCE.CHUNK_FLAG.get().set(true); - entityPlayer.connection.send(nmsPacket); - } finally { - FaweCache.INSTANCE.CHUNK_FLAG.get().set(false); - } - } - }); - } - } - - @Override - public Map> getProperties(BlockType blockType) { - return getParent().getProperties(blockType); - } - - @Override - public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) { - int internalId = BlockStateIdAccess.getBlockStateId(blockState); - net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); - return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) - ); - } - - @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { - ItemStack stack = new ItemStack( - Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), - baseItemStack.getAmount() - ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt()))); - return CraftItemStack.asCraftMirror(stack); - } - - @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; - } - - @Override - public List getEntities(org.bukkit.World world) { - // Quickly add each entity to a list copy. - List mcEntities = new ArrayList<>(); - ((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add); - - List list = new ArrayList<>(); - mcEntities.forEach((mcEnt) -> { - org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); - if (bukkitEntity.isValid()) { - list.add(bukkitEntity); - } - - }); - return list; - } - - @Override - public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { - final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; - } - - @Override - public Tag toNative(net.minecraft.nbt.Tag foreign) { - return parent.toNative(foreign); - } - - @Override - public net.minecraft.nbt.Tag fromNative(Tag foreign) { - if (foreign instanceof PaperweightLazyCompoundTag) { - return ((PaperweightLazyCompoundTag) foreign).get(); - } - return parent.fromNative(foreign); - } - - @Override - public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception { - return new PaperweightRegen(bukkitWorld, region, target, options).regenerate(); - } - - @Override - public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) { - return new PaperweightGetBlocks(world, chunkX, chunkZ); - } - - @Override - public int getInternalBiomeId(BiomeType biomeType) { - final Registry registry = MinecraftServer - .getServer() - .registryAccess() - .ownedRegistryOrThrow(Registry.BIOME_REGISTRY); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); - Biome biome = registry.get(resourceLocation); - return registry.getId(biome); - } - - @Override - public Iterable getRegisteredBiomes() { - WritableRegistry biomeRegistry = ((CraftServer) Bukkit.getServer()) - .getServer() - .registryAccess() - .ownedRegistryOrThrow( - Registry.BIOME_REGISTRY); - List keys = biomeRegistry.stream() - .map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); - List namespacedKeys = new ArrayList<>(); - for (ResourceLocation key : keys) { - try { - namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key)); - } catch (IllegalArgumentException e) { - LOGGER.error("Error converting biome key {}", key.toString(), e); - } - } - return namespacedKeys; - } - - @Override - public RelighterFactory getRelighterFactory() { - try { - Class.forName("ca.spottedleaf.starlight.light.StarLightEngine"); - if (PaperweightStarlightRelighter.isUsable()) { - return new PaperweightStarlightRelighterFactory(); - } - } catch (ThreadDeath td) { - throw td; - } catch (Throwable ignored) { - - } - return new NMSRelighterFactory(); - } - - @Override - public Map>> getAllProperties() { - if (initialised) { - return allBlockProperties; - } - synchronized (this) { - if (initialised) { - return allBlockProperties; - } - init(); - return allBlockProperties; - } - } - - @Override - public IBatchProcessor getTickingPostProcessor() { - return new PaperweightPostProcessor(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java deleted file mode 100644 index aab9e5aa7..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java +++ /dev/null @@ -1,1069 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks; -import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.fastasyncworldedit.core.math.BitArrayUnstretched; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import io.papermc.lib.PaperLib; -import io.papermc.paper.event.block.BeaconDeactivatedEvent; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; -import net.minecraft.nbt.IntTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.util.BitStorage; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.entity.BeaconBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkBiomeContainer; -import net.minecraft.world.level.chunk.DataLayer; -import net.minecraft.world.level.chunk.HashMapPalette; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.LinearPalette; -import net.minecraft.world.level.chunk.Palette; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.lighting.LevelLightEngine; -import org.apache.logging.log4j.Logger; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock; -import org.bukkit.event.entity.CreatureSpawnEvent; - -import javax.annotation.Nonnull; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.Semaphore; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize( - () -> tileEntity.save(new net.minecraft.nbt.CompoundTag()))); - private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin - .getInstance() - .getBukkitImplAdapter()); - private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); - private final ServerLevel serverLevel; - private final int chunkX; - private final int chunkZ; - private final int minHeight; - private final int maxHeight; - private final int minSectionPosition; - private final int maxSectionPosition; - private LevelChunkSection[] sections; - private LevelChunk levelChunk; - private DataLayer[] blockLight; - private DataLayer[] skyLight; - private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; - private boolean forceLoadSections = true; - private boolean lightUpdate = false; - - public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { - this(((CraftWorld) world).getHandle(), chunkX, chunkZ); - } - - public PaperweightGetBlocks(ServerLevel serverLevel, int chunkX, int chunkZ) { - super(serverLevel.getMinBuildHeight() >> 4, (serverLevel.getMaxBuildHeight() - 1) >> 4); - this.serverLevel = serverLevel; - this.chunkX = chunkX; - this.chunkZ = chunkZ; - this.minHeight = serverLevel.getMinBuildHeight(); - this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.minSectionPosition = minHeight >> 4; - this.maxSectionPosition = maxHeight >> 4; - this.skyLight = new DataLayer[getSectionCount()]; - this.blockLight = new DataLayer[getSectionCount()]; - } - - public int getChunkX() { - return chunkX; - } - - public int getChunkZ() { - return chunkZ; - } - - @Override - public boolean isCreateCopy() { - return createCopy; - } - - @Override - public void setCreateCopy(boolean createCopy) { - this.createCopy = createCopy; - } - - @Override - public IChunkGet getCopy() { - return copy; - } - - @Override - public void setLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { - if (light != null) { - lightUpdate = true; - try { - fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void setSkyLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { - if (light != null) { - lightUpdate = true; - try { - fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void setHeightmapToGet(HeightMapType type, int[] data) { - // height + 1 to match server internal - BitArrayUnstretched bitArray = new BitArrayUnstretched(MathMan.log2nlz(getChunk().getHeight() + 1), 256); - bitArray.fromRaw(data); - Heightmap.Types nativeType = Heightmap.Types.valueOf(type.name()); - Heightmap heightMap = getChunk().heightmaps.get(nativeType); - heightMap.setRawData(getChunk(), nativeType, bitArray.getData()); - } - - @Override - public int getMaxY() { - return maxHeight; - } - - @Override - public int getMinY() { - return minHeight; - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - ChunkBiomeContainer index = getChunk().getBiomes(); - Biome biomes = null; - if (y == -1) { - for (y = serverLevel.getMinBuildHeight(); y < serverLevel.getMaxBuildHeight(); y += 4) { - biomes = index.getNoiseBiome(x >> 2, y >> 2, z >> 2); - if (biomes != null) { - break; - } - } - } else { - biomes = index.getNoiseBiome(x >> 2, y >> 2, z >> 2); - } - return biomes != null ? PaperweightPlatformAdapter.adapt(biomes, serverLevel) : null; - } - - @Override - public void removeSectionLighting(int layer, boolean sky) { - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.BLOCK).getDataLayerData( - sectionPos); - if (dataLayer != null) { - lightUpdate = true; - synchronized (dataLayer) { - byte[] bytes = PaperLib.isPaper() ? dataLayer.getIfSet() : dataLayer.getData(); - if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) { - Arrays.fill(bytes, (byte) 0); - } - } - } - if (sky) { - SectionPos sectionPos1 = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer1 = serverLevel - .getChunkSource() - .getLightEngine() - .getLayerListener(LightLayer.SKY) - .getDataLayerData(sectionPos1); - if (dataLayer1 != null) { - lightUpdate = true; - synchronized (dataLayer1) { - byte[] bytes = PaperLib.isPaper() ? dataLayer1.getIfSet() : dataLayer1.getData(); - if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) { - Arrays.fill(bytes, (byte) 0); - } - } - } - } - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( - chunkX << 4), y, (z & 15) + ( - chunkZ << 4))); - if (blockEntity == null) { - return null; - } - return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag()))); - } - - @Override - public Map getTiles() { - Map nmsTiles = getChunk().getBlockEntities(); - if (nmsTiles.isEmpty()) { - return Collections.emptyMap(); - } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); - } - - @Override - public int getSkyLight(int x, int y, int z) { - int layer = y >> 4; - int alayer = layer - getMinSectionPosition(); - if (skyLight[alayer] == null) { - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = - serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.SKY).getDataLayerData(sectionPos); - // If the server hasn't generated the section's NibbleArray yet, it will be null - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. - Arrays.fill(LAYER_COUNT, (byte) 15); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( - LightLayer.BLOCK, - sectionPos, - dataLayer, - true - ); - } - skyLight[alayer] = dataLayer; - } - return skyLight[alayer].get(x & 15, y & 15, z & 15); - } - - @Override - public int getEmittedLight(int x, int y, int z) { - int layer = y >> 4; - int alayer = layer - getMinSectionPosition(); - if (blockLight[alayer] == null) { - serverLevel.getRawBrightness(new BlockPos(1, 1, 1), 5); - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = serverLevel - .getChunkSource() - .getLightEngine() - .getLayerListener(LightLayer.BLOCK) - .getDataLayerData(sectionPos); - // If the server hasn't generated the section's DataLayer yet, it will be null - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. - Arrays.fill(LAYER_COUNT, (byte) 15); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true - ); - } - blockLight[alayer] = dataLayer; - } - return blockLight[alayer].get(x & 15, y & 15, z & 15); - } - - @Override - public int[] getHeightMap(HeightMapType type) { - long[] longArray = getChunk().heightmaps.get(Heightmap.Types.valueOf(type.name())).getRawData(); - BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256, longArray); - return bitArray.toRaw(new int[256]); - } - - @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); - if (entity != null) { - org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); - } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { - return tag; - } - } - return null; - } - - @Override - public Set getEntities() { - List entities = PaperweightPlatformAdapter.getEntities(getChunk()); - if (entities.isEmpty()) { - return Collections.emptySet(); - } - int size = entities.size(); - return new AbstractSet<>() { - @Override - public int size() { - return size; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { - return false; - } - UUID getUUID = getTag.getUUID(); - for (Entity entity : entities) { - UUID uuid = entity.getUUID(); - if (uuid.equals(getUUID)) { - return true; - } - } - return false; - } - - @Nonnull - @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); - return result.iterator(); - } - }; - } - - private void removeEntity(Entity entity) { - entity.discard(); - } - - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) { - return PaperweightPlatformAdapter.ensureLoaded(nmsWorld, chunkX, chunkZ); - } - - @Override - @SuppressWarnings("rawtypes") - public synchronized > T call(IChunkSet set, Runnable finalizer) { - forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; - try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - boolean fastmode = set.isFastMode() && Settings.settings().QUEUE.NO_TICK_FASTMODE; - - // Remove existing tiles. Create a copy so that we can remove blocks - Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); - List beacons = null; - if (!chunkTiles.isEmpty()) { - for (Map.Entry entry : chunkTiles.entrySet()) { - final BlockPos pos = entry.getKey(); - final int lx = pos.getX() & 15; - final int ly = pos.getY(); - final int lz = pos.getZ() & 15; - final int layer = ly >> 4; - if (!set.hasSection(layer)) { - continue; - } - - int ordinal = set.getBlock(lx, ly, lz).getOrdinal(); - if (ordinal != BlockTypesCache.ReservedIDs.__RESERVED__) { - BlockEntity tile = entry.getValue(); - if (PaperLib.isPaper() && tile instanceof BeaconBlockEntity) { - if (beacons == null) { - beacons = new ArrayList<>(); - } - beacons.add(tile); - PaperweightPlatformAdapter.removeBeacon(tile, nmsChunk); - continue; - } - nmsChunk.removeBlockEntity(tile.getBlockPos()); - if (createCopy) { - copy.storeTile(tile); - } - } - } - } - - int bitMask = 0; - synchronized (nmsChunk) { - LevelChunkSection[] levelChunkSections = nmsChunk.getSections(); - - for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) { - if (!set.hasSection(layerNo)) { - continue; - } - int layer = layerNo - getMinSectionPosition(); - - bitMask |= 1 << layer; - - // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to - // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); - - // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was - // submitted to keep loaded internal chunks to queue target size. - synchronized (super.sectionLocks[layer]) { - if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(layer, copyArr); - } - - LevelChunkSection newSection; - LevelChunkSection existingSection = levelChunkSections[layer]; - // Don't attempt to tick section whilst we're editing - if (existingSection != null) { - PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } - } - - if (existingSection == null) { - newSection = PaperweightPlatformAdapter.newChunkSection(layerNo, setArr, fastmode, adapter); - if (PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, null, newSection, layer)) { - updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer); - continue; - } else { - existingSection = levelChunkSections[layer]; - if (existingSection == null) { - LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, - +layer - ); - continue; - } - } - } - - //ensure that the server doesn't try to tick the chunksection while we're editing it (again). - PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } - DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection); - - // Synchronize to prevent further acquisitions - synchronized (lock) { - lock.acquire(); // Wait until we have the lock - lock.release(); - try { - sectionLock.writeLock().lock(); - if (this.getChunk() != nmsChunk) { - this.levelChunk = nmsChunk; - this.sections = null; - this.reset(); - } else if (existingSection != getSections(false)[layer]) { - this.sections[layer] = existingSection; - this.reset(); - } else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layerNo))) { - this.reset(layerNo); - /*} else if (lock.isModified()) { - this.reset(layerNo);*/ - } - } finally { - sectionLock.writeLock().unlock(); - } - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - fastmode, - adapter - ); - if (!PaperweightPlatformAdapter.setSectionAtomic( - levelChunkSections, - existingSection, - newSection, - layer - )) { - LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, - +layer - ); - } else { - updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer); - } - } - } - } - - // Biomes - BiomeType[][] biomes = set.getBiomes(); - if (biomes != null) { - // set biomes - ChunkBiomeContainer currentBiomes = nmsChunk.getBiomes(); - if (createCopy) { - copy.storeBiomes(currentBiomes); - } - for (int layer = 0; layer < 16; layer++) { - if (biomes[layer] == null) { - continue; - } - for (int y = 0, i = 0; y < 4; y++) { - for (int z = 0; z < 4; z++) { - for (int x = 0; x < 4; x++, i++) { - final BiomeType biome = biomes[layer][i]; - if (biome != null) { - Biome nmsBiome = - nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get( - ResourceLocation.tryParse(biome.getId())); - if (nmsBiome == null) { - throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId()); - } - currentBiomes.setBiome(x, (layer << 2) + y, z, nmsBiome); - } - } - } - } - } - } - - Map heightMaps = set.getHeightMaps(); - for (Map.Entry entry : heightMaps.entrySet()) { - PaperweightGetBlocks.this.setHeightmapToGet(entry.getKey(), entry.getValue()); - } - PaperweightGetBlocks.this.setLightingToGet( - set.getLight(), - set.getMinSectionPosition(), - set.getMaxSectionPosition() - ); - PaperweightGetBlocks.this.setSkyLightingToGet( - set.getSkyLight(), - set.getMinSectionPosition(), - set.getMaxSectionPosition() - ); - - Runnable[] syncTasks = null; - - int bx = chunkX << 4; - int bz = chunkZ << 4; - - // Call beacon deactivate events here synchronously - // list will be null on spigot, so this is an implicit isPaper check - if (beacons != null && !beacons.isEmpty()) { - final List finalBeacons = beacons; - - syncTasks = new Runnable[4]; - - syncTasks[3] = () -> { - for (BlockEntity beacon : finalBeacons) { - BeaconBlockEntity.playSound(beacon.getLevel(), beacon.getBlockPos(), SoundEvents.BEACON_DEACTIVATE); - new BeaconDeactivatedEvent(CraftBlock.at(beacon.getLevel(), beacon.getBlockPos())).callEvent(); - } - }; - } - - Set entityRemoves = set.getEntityRemoves(); - if (entityRemoves != null && !entityRemoves.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[3]; - } - - syncTasks[2] = () -> { - Set entitiesRemoved = new HashSet<>(); - final List entities = PaperweightPlatformAdapter.getEntities(nmsChunk); - - for (Entity entity : entities) { - UUID uuid = entity.getUUID(); - if (entityRemoves.contains(uuid)) { - if (createCopy) { - copy.storeEntity(entity); - } - removeEntity(entity); - entitiesRemoved.add(uuid); - entityRemoves.remove(uuid); - } - } - if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { - for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); - if (entity != null) { - removeEntity(entity); - } - } - } - // Only save entities that were actually removed to history - set.getEntityRemoves().clear(); - set.getEntityRemoves().addAll(entitiesRemoved); - }; - } - - Set entities = set.getEntities(); - if (entities != null && !entities.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[2]; - } - - syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); - while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); - if (idTag == null || posTag == null || rotTag == null) { - LOGGER.error("Unknown entity tag: {}", nativeTag); - continue; - } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); - - EntityType type = EntityType.byString(id).orElse(null); - if (type != null) { - Entity entity = type.create(nmsWorld); - if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); - for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.load(tag); - entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { - LOGGER.warn( - "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", - id, - nmsWorld.getWorld().getName(), - x, - y, - z - ); - // Unsuccessful create should not be saved to history - iterator.remove(); - } - } - } - } - }; - } - - // set tiles - Map tiles = set.getTiles(); - if (tiles != null && !tiles.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[1]; - } - - syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); - final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; - final BlockPos pos = new BlockPos(x, y, z); - - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); - if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); - } - if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - tileEntity.load(tag); - } - } - } - }; - } - - Runnable callback; - if (bitMask == 0 && biomes == null && !lightUpdate) { - callback = null; - } else { - int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; - callback = () -> { - // Set Modified - nmsChunk.setLightCorrect(true); // Set Modified - nmsChunk.mustNotSave = false; - nmsChunk.markUnsaved(); - // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); - } - if (finalizer != null) { - finalizer.run(); - } - }; - } - if (syncTasks != null) { - QueueHandler queueHandler = Fawe.instance().getQueueHandler(); - Runnable[] finalSyncTasks = syncTasks; - - // Chain the sync tasks and the callback - Callable chain = () -> { - try { - // Run the sync tasks - for (Runnable task : finalSyncTasks) { - if (task != null) { - task.run(); - } - } - if (callback == null) { - if (finalizer != null) { - finalizer.run(); - } - return null; - } else { - return queueHandler.async(callback, null); - } - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - }; - //noinspection unchecked - required at compile time - return (T) (Future) queueHandler.sync(chain); - } else { - if (callback == null) { - if (finalizer != null) { - finalizer.run(); - } - } else { - callback.run(); - } - } - } - return null; - } catch (Throwable e) { - e.printStackTrace(); - return null; - } finally { - forceLoadSections = true; - } - } - - private void updateGet( - LevelChunk nmsChunk, - LevelChunkSection[] chunkSections, - LevelChunkSection section, - char[] arr, - int layer - ) { - try { - sectionLock.writeLock().lock(); - if (this.getChunk() != nmsChunk) { - this.levelChunk = nmsChunk; - this.sections = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); - this.reset(); - } - if (this.sections == null) { - this.sections = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); - } - if (this.sections[layer] != section) { - // Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords - this.sections[layer] = new LevelChunkSection[]{section}.clone()[0]; - } - } finally { - sectionLock.writeLock().unlock(); - } - this.blocks[layer] = arr; - } - - private char[] loadPrivately(int layer) { - layer -= getMinSectionPosition(); - if (super.sections[layer] != null) { - synchronized (super.sectionLocks[layer]) { - if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; - } - } - } - return PaperweightGetBlocks.this.update(layer, null, true); - } - - @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); - } - - /** - * Update a given (nullable) data array to the current data stored in the server's chunk, associated with this - * {@link PaperweightPlatformAdapter} instance. Not synchronised to the {@link PaperweightPlatformAdapter} instance as synchronisation - * is handled where necessary in the method, and should otherwise be handled correctly by this method's caller. - * - * @param layer layer index (0 may denote a negative layer in the world, e.g. at y=-32) - * @param data array to be updated/filled with data or null - * @param aggressive if the cached section array should be re-acquired. - * @return the given array to be filled with data, or a new array if null is given. - */ - @Override - @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { - LevelChunkSection section = getSections(aggressive)[layer]; - // Section is null, return empty array - if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; - } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - Semaphore lock = PaperweightPlatformAdapter.applyLock(section); - synchronized (lock) { - // Efficiently convert ChunkSection to raw data - try { - lock.acquire(); - - final PalettedContainer blocks = section.getStates(); - final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(blocks); - final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get(blocks); - - final int bitsPerEntry = (int) PaperweightPlatformAdapter.fieldBitsPerEntry.get(bits); - final long[] blockStates = bits.getRaw(); - - new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data); - - int num_palette; - if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { - num_palette = palette.getSize(); - } else { - // The section's palette is the global block palette. - for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; - char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; - } - return data; - } - - char[] paletteToOrdinal = FaweCache.INSTANCE.PALETTE_TO_BLOCK_CHAR.get(); - try { - if (num_palette != 1) { - for (int i = 0; i < num_palette; i++) { - char ordinal = ordinal(palette.valueFor(i), adapter); - paletteToOrdinal[i] = ordinal; - } - for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; - char val = paletteToOrdinal[paletteVal]; - if (val == Character.MAX_VALUE) { - val = ordinal(palette.valueFor(i), adapter); - paletteToOrdinal[i] = val; - } - data[i] = val; - } - } else { - char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); - } - } finally { - for (int i = 0; i < num_palette; i++) { - paletteToOrdinal[i] = Character.MAX_VALUE; - } - } - return data; - } catch (IllegalAccessException | InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } finally { - lock.release(); - } - } - } - - private char ordinal(net.minecraft.world.level.block.state.BlockState ibd, PaperweightFaweAdapter adapter) { - if (ibd == null) { - return BlockTypesCache.ReservedIDs.AIR; - } else { - return adapter.adaptToChar(ibd); - } - } - - public LevelChunkSection[] getSections(boolean force) { - force &= forceLoadSections; - sectionLock.readLock().lock(); - LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); - if (tmp == null || force) { - try { - sectionLock.writeLock().lock(); - tmp = sections; - if (tmp == null || force) { - LevelChunkSection[] chunkSections = getChunk().getSections(); - tmp = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length); - sections = tmp; - } - } finally { - sectionLock.writeLock().unlock(); - } - } - return tmp; - } - - public LevelChunk getChunk() { - LevelChunk levelChunk = this.levelChunk; - if (levelChunk == null) { - synchronized (this) { - levelChunk = this.levelChunk; - if (levelChunk == null) { - this.levelChunk = levelChunk = ensureLoaded(this.serverLevel, chunkX, chunkZ); - } - } - } - return levelChunk; - } - - private void fillLightNibble(char[][] light, LightLayer lightLayer, int minSectionPosition, int maxSectionPosition) { - for (int Y = 0; Y <= maxSectionPosition - minSectionPosition; Y++) { - if (light[Y] == null) { - continue; - } - SectionPos sectionPos = SectionPos.of(levelChunk.getPos(), Y + minSectionPosition); - DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(lightLayer).getDataLayerData( - sectionPos); - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - Arrays.fill(LAYER_COUNT, lightLayer == LightLayer.SKY ? (byte) 15 : (byte) 0); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( - lightLayer, - sectionPos, - dataLayer, - true - ); - } - synchronized (dataLayer) { - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - int i = y << 8 | z << 4 | x; - if (light[Y][i] < 16) { - dataLayer.set(x, y, z, light[Y][i]); - } - } - } - } - } - } - } - - @Override - public boolean hasSection(int layer) { - layer -= getMinSectionPosition(); - return getSections(false)[layer] != null; - } - - @Override - @SuppressWarnings("unchecked") - public synchronized boolean trim(boolean aggressive) { - skyLight = new DataLayer[getSectionCount()]; - blockLight = new DataLayer[getSectionCount()]; - if (aggressive) { - sectionLock.writeLock().lock(); - sections = null; - levelChunk = null; - sectionLock.writeLock().unlock(); - return super.trim(true); - } else if (sections == null) { - // don't bother trimming if there are no sections stored. - return true; - } else { - for (int i = getMinSectionPosition(); i <= getMaxSectionPosition(); i++) { - int layer = i - getMinSectionPosition(); - if (!hasSection(i) || !super.sections[layer].isFull()) { - continue; - } - LevelChunkSection existing = getSections(true)[layer]; - try { - final PalettedContainer blocksExisting = existing.getStates(); - - final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get( - blocksExisting); - int paletteSize; - - if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { - paletteSize = palette.getSize(); - } else { - super.trim(false, i); - continue; - } - if (paletteSize == 1) { - //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. - continue; - } - super.trim(false, i); - } catch (IllegalAccessException ignored) { - super.trim(false, i); - } - } - return true; - } - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java deleted file mode 100644 index de431c718..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.fastasyncworldedit.core.queue.IBlocks; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.ChunkBiomeContainer; -import net.minecraft.world.level.chunk.LevelChunk; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Future; - -public class PaperweightGetBlocks_Copy implements IChunkGet { - - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); - private final char[][] blocks; - private final int minHeight; - private final int maxHeight; - final ServerLevel serverLevel; - final LevelChunk levelChunk; - private ChunkBiomeContainer chunkBiomeContainer; - - protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { - this.levelChunk = levelChunk; - this.serverLevel = levelChunk.level; - this.minHeight = serverLevel.getMinBuildHeight(); - this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; - } - - protected void storeTile(BlockEntity blockEntity) { - tiles.put( - BlockVector3.at( - blockEntity.getBlockPos().getX(), - blockEntity.getBlockPos().getY(), - blockEntity.getBlockPos().getZ() - ), - new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag()))) - ); - } - - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); - } - - @Override - public Set getEntities() { - return this.entities; - } - - @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { - return tag; - } - } - return null; - } - - @Override - public boolean isCreateCopy() { - return false; - } - - @Override - public void setCreateCopy(boolean createCopy) { - } - - @Override - public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - } - - @Override - public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - } - - @Override - public void setHeightmapToGet(HeightMapType type, int[] data) { - } - - @Override - public int getMaxY() { - return maxHeight; - } - - @Override - public int getMinY() { - return minHeight; - } - - @Override - public int getMaxSectionPosition() { - return maxHeight >> 4; - } - - @Override - public int getMinSectionPosition() { - return minHeight >> 4; - } - - protected void storeBiomes(ChunkBiomeContainer chunkBiomeContainer) { - // The to do one line below is pre-paperweight and needs to be revised - // TODO revisit last parameter, BiomeStorage[] *would* be more efficient - this.chunkBiomeContainer = new ChunkBiomeContainer(chunkBiomeContainer.biomeRegistry, serverLevel, - chunkBiomeContainer.writeBiomes() - ); - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - Biome biome = null; - if (y == -1) { - for (y = serverLevel.getMinBuildHeight(); y <= serverLevel.getMaxBuildHeight(); y += 4) { - biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2); - if (biome != null) { - break; - } - } - } else { - biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2); - } - return biome != null ? PaperweightPlatformAdapter.adapt(biome, serverLevel) : null; - } - - @Override - public void removeSectionLighting(int layer, boolean sky) { - } - - @Override - public boolean trim(boolean aggressive, int layer) { - return false; - } - - @Override - public IBlocks reset() { - return null; - } - - @Override - public int getSectionCount() { - return serverLevel.getSectionsCount(); - } - - protected void storeSection(int layer, char[] data) { - blocks[layer] = data; - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); - } - - @Override - public boolean hasSection(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer] != null; - } - - @Override - public char[] load(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer]; - } - - @Override - public char[] loadIfPresent(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer]; - } - - @Override - public BlockState getBlock(int x, int y, int z) { - return BlockTypesCache.states[get(x, y, z)]; - } - - @Override - public int getSkyLight(int x, int y, int z) { - return 0; - } - - @Override - public int getEmittedLight(int x, int y, int z) { - return 0; - } - - @Override - public int[] getHeightMap(HeightMapType type) { - return new int[0]; - } - - @Override - public > T call(IChunkSet set, Runnable finalize) { - return null; - } - - public char get(int x, int y, int z) { - final int layer = (y >> 4) - getMinSectionPosition(); - final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; - } - - - @Override - public boolean trim(boolean aggressive) { - return false; - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightMapChunkUtil.java deleted file mode 100644 index c9d5ed124..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightMapChunkUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; - -public class PaperweightMapChunkUtil extends MapChunkUtil { - - public PaperweightMapChunkUtil() throws NoSuchFieldException { - fieldX = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a")); - fieldZ = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("x", "b")); - fieldBitMask = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("z", "c")); - fieldHeightMap = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("availableSections", "d")); - fieldChunkData = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("biomes", "f")); - fieldBlockEntities = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("buffer", "g")); - fieldFull = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("blockEntitiesTags", "h")); - fieldX.setAccessible(true); - fieldZ.setAccessible(true); - fieldBitMask.setAccessible(true); - fieldHeightMap.setAccessible(true); - fieldChunkData.setAccessible(true); - fieldBlockEntities.setAccessible(true); - fieldFull.setAccessible(true); - } - - @Override - public ClientboundLevelChunkPacket createPacket() { - // TODO ??? return new ClientboundLevelChunkPacket(); - throw new UnsupportedOperationException(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java deleted file mode 100644 index 688a84a14..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java +++ /dev/null @@ -1,511 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; -import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.math.BitArrayUnstretched; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.mojang.datafixers.util.Either; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import io.papermc.lib.PaperLib; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.BitStorage; -import net.minecraft.util.Unit; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.ChunkBiomeContainer; -import net.minecraft.world.level.chunk.HashMapPalette; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.LinearPalette; -import net.minecraft.world.level.chunk.Palette; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.gameevent.GameEventDispatcher; -import net.minecraft.world.level.gameevent.GameEventListener; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_17_R1.CraftChunk; -import sun.misc.Unsafe; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Function; -import java.util.stream.Stream; - -public final class PaperweightPlatformAdapter extends NMSAdapter { - - public static final Field fieldStorage; - public static final Field fieldPalette; - public static final Field fieldBits; - - public static final Field fieldBitsPerEntry; - - private static final Field fieldTickingFluidContent; - private static final Field fieldTickingBlockCount; - private static final Field fieldNonEmptyBlockCount; - - private static final Field fieldBiomes; - - private static final MethodHandle methodGetVisibleChunk; - - private static final int CHUNKSECTION_BASE; - private static final int CHUNKSECTION_SHIFT; - - private static final Field fieldLock; - private static final long fieldLockOffset; - - private static final Field fieldGameEventDispatcherSections; - private static final MethodHandle methodremoveBlockEntityTicker; - - private static final Field fieldRemove; - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - static { - try { - fieldBits = PalettedContainer.class.getDeclaredField(Refraction.pickName("bits", "l")); - fieldBits.setAccessible(true); - fieldStorage = PalettedContainer.class.getDeclaredField(Refraction.pickName("storage", "c")); - fieldStorage.setAccessible(true); - fieldPalette = PalettedContainer.class.getDeclaredField(Refraction.pickName("palette", "k")); - fieldPalette.setAccessible(true); - - fieldBitsPerEntry = BitStorage.class.getDeclaredField(Refraction.pickName("bits", "c")); - fieldBitsPerEntry.setAccessible(true); - - fieldTickingFluidContent = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h")); - fieldTickingFluidContent.setAccessible(true); - fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g")); - fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f")); - fieldNonEmptyBlockCount.setAccessible(true); - - fieldBiomes = ChunkBiomeContainer.class.getDeclaredField(Refraction.pickName("biomes", "f")); - fieldBiomes.setAccessible(true); - - Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( - "getVisibleChunkIfPresent", - "getVisibleChunk" - ), long.class); - getVisibleChunkIfPresent.setAccessible(true); - methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent); - - Unsafe unsafe = ReflectionUtils.getUnsafe(); - if (!PaperLib.isPaper()) { - - fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m")); - fieldLockOffset = unsafe.objectFieldOffset(fieldLock); - } else { - // in paper, the used methods are synchronized properly - fieldLock = null; - fieldLockOffset = -1; - } - - fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName( - "gameEventDispatcherSections", "x")); - fieldGameEventDispatcherSections.setAccessible(true); - Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod( - Refraction.pickName( - "removeBlockEntityTicker", - "l" - ), BlockPos.class - ); - removeBlockEntityTicker.setAccessible(true); - methodremoveBlockEntityTicker = MethodHandles.lookup().unreflect(removeBlockEntityTicker); - - fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); - fieldRemove.setAccessible(true); - - CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class); - int scale = unsafe.arrayIndexScale(LevelChunkSection[].class); - if ((scale & (scale - 1)) != 0) { - throw new Error("data type scale not a power of two"); - } - CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); - } catch (RuntimeException e) { - throw e; - } catch (Throwable rethrow) { - rethrow.printStackTrace(); - throw new RuntimeException(rethrow); - } - } - - static boolean setSectionAtomic( - LevelChunkSection[] sections, - LevelChunkSection expected, - LevelChunkSection value, - int layer - ) { - long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE; - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; - } - - // There is no point in having a functional semaphore for paper servers. - private static final ThreadLocal SEMAPHORE_THREAD_LOCAL = - ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null)); - - static DelegateSemaphore applyLock(LevelChunkSection section) { - if (PaperLib.isPaper()) { - return SEMAPHORE_THREAD_LOCAL.get(); - } - try { - synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); - PalettedContainer blocks = section.getStates(); - Semaphore currentLock = (Semaphore) unsafe.getObject(blocks, fieldLockOffset); - if (currentLock instanceof DelegateSemaphore delegateSemaphore) { - return delegateSemaphore; - } - DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(blocks, fieldLockOffset, newLock); - return newLock; - } - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) { - if (!PaperLib.isPaper()) { - LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false); - if (nmsChunk != null) { - return nmsChunk; - } - if (Fawe.isMainThread()) { - return serverLevel.getChunk(chunkX, chunkZ); - } - } else { - LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); - if (nmsChunk != null) { - addTicket(serverLevel, chunkX, chunkZ); - return nmsChunk; - } - nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); - if (nmsChunk != null) { - addTicket(serverLevel, chunkX, chunkZ); - return nmsChunk; - } - // Avoid "async" methods from the main thread. - if (Fawe.isMainThread()) { - return serverLevel.getChunk(chunkX, chunkZ); - } - CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); - try { - CraftChunk chunk; - try { - chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); - } catch (TimeoutException e) { - String world = serverLevel.getWorld().getName(); - // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); - if (loaded) { - LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); - // Retry chunk load - chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); - } else { - throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); - } - } - return chunk.getHandle(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); - } - - private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { - // Ensure chunk is definitely loaded before applying a ticket - net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); - } - - public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { - ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap; - try { - return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ)); - } catch (Throwable thr) { - throw new RuntimeException(thr); - } - } - - @SuppressWarnings("unchecked") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { - ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); - if (chunkHolder == null) { - return; - } - ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ); - // UNLOADED_CHUNK - Optional optional = ((Either) chunkHolder - .getTickingChunkFuture() - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - if (PaperLib.isPaper()) { - // getChunkAtIfLoadedImmediately is paper only - optional = optional.or(() -> Optional.ofNullable(nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ))); - } - if (optional.isEmpty()) { - return; - } - LevelChunk levelChunk = optional.get(); - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk); - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket)); - if (lighting) { - //This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad) - boolean trustEdges = true; - ClientboundLightUpdatePacket packet = - new ClientboundLightUpdatePacket(coordIntPair, nmsWorld.getChunkSource().getLightEngine(), null, null, - trustEdges - ); - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - } - }); - } - - private static Stream nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { - return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false); - } - - /* - NMS conversion - */ - public static LevelChunkSection newChunkSection( - final int layer, - final char[] blocks, - boolean fastMode, - CachedBukkitAdapter adapter - ) { - return newChunkSection(layer, null, blocks, fastMode, adapter); - } - - public static LevelChunkSection newChunkSection( - final int layer, - final Function get, - char[] set, - boolean fastMode, - CachedBukkitAdapter adapter - ) { - if (set == null) { - return newChunkSection(layer); - } - final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); - final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); - final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get(); - final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get(); - try { - int num_palette; - final short[] nonEmptyBlockCount = fastMode ? new short[1] : null; - if (get == null) { - num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, nonEmptyBlockCount); - } else { - num_palette = createPalette( - layer, - blockToPalette, - paletteToBlock, - blocksCopy, - get, - set, - adapter, - nonEmptyBlockCount - ); - } - // BlockStates - int bitsPerEntry = MathMan.log2nlz(num_palette - 1); - if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) { - bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry - } else { - bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries - } - if (bitsPerEntry > 8) { - bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1); - } - - final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntry); - final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong); - - if (num_palette == 1) { - for (int i = 0; i < blockBitArrayEnd; i++) { - blockStates[i] = 0; - } - } else { - final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntry, 4096, blockStates); - bitArray.fromRaw(blocksCopy); - } - - LevelChunkSection levelChunkSection = newChunkSection(layer); - // set palette & data bits - final PalettedContainer dataPaletteBlocks = - levelChunkSection.getStates(); - // private DataPalette h; - // protected DataBits a; - final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd); - final BitStorage nmsBits = new BitStorage(bitsPerEntry, 4096, bits); - final Palette blockStatePalettedContainer; - if (bitsPerEntry <= 4) { - blockStatePalettedContainer = new LinearPalette<>(Block.BLOCK_STATE_REGISTRY, bitsPerEntry, dataPaletteBlocks, - NbtUtils::readBlockState - ); - } else if (bitsPerEntry < 9) { - blockStatePalettedContainer = new HashMapPalette<>( - Block.BLOCK_STATE_REGISTRY, - bitsPerEntry, - dataPaletteBlocks, - NbtUtils::readBlockState, - NbtUtils::writeBlockState - ); - } else { - blockStatePalettedContainer = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE; - } - - // set palette if required - if (bitsPerEntry < 9) { - for (int i = 0; i < num_palette; i++) { - final int ordinal = paletteToBlock[i]; - blockToPalette[ordinal] = Integer.MAX_VALUE; - final BlockState state = BlockTypesCache.states[ordinal]; - final net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - blockStatePalettedContainer.idFor(blockState); - } - } - try { - fieldStorage.set(dataPaletteBlocks, nmsBits); - fieldPalette.set(dataPaletteBlocks, blockStatePalettedContainer); - fieldBits.set(dataPaletteBlocks, bitsPerEntry); - } catch (final IllegalAccessException e) { - throw new RuntimeException(e); - } - - if (!fastMode) { - levelChunkSection.recalcBlockCounts(); - } else { - try { - fieldNonEmptyBlockCount.set(levelChunkSection, nonEmptyBlockCount[0]); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return levelChunkSection; - } catch (final Throwable e) { - throw e; - } finally { - Arrays.fill(blockToPalette, Integer.MAX_VALUE); - Arrays.fill(paletteToBlock, Integer.MAX_VALUE); - Arrays.fill(blockStates, 0); - Arrays.fill(blocksCopy, 0); - } - } - - private static LevelChunkSection newChunkSection(int layer) { - return new LevelChunkSection(layer); - } - - public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException { - fieldTickingFluidContent.setShort(section, (short) 0); - fieldTickingBlockCount.setShort(section, (short) 0); - } - - public static Biome[] getBiomeArray(ChunkBiomeContainer chunkBiomeContainer) { - try { - return (Biome[]) fieldBiomes.get(chunkBiomeContainer); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return null; - } - } - - public static BiomeType adapt(Biome biome, LevelAccessor levelAccessor) { - ResourceLocation resourceLocation = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getKey( - biome); - if (resourceLocation == null) { - return levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getId(biome) == -1 - ? BiomeTypes.OCEAN - : null; - } - return BiomeTypes.get(resourceLocation.toString().toLowerCase(Locale.ROOT)); - } - - @SuppressWarnings("unchecked") - static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { - try { - // Do the method ourselves to avoid trying to reflect generic method parameters - if (levelChunk.loaded || levelChunk.level.isClientSide()) { - BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos()); - if (blockEntity != null) { - if (!levelChunk.level.isClientSide) { - Block block = beacon.getBlockState().getBlock(); - if (block instanceof EntityBlock) { - GameEventListener gameEventListener = ((EntityBlock) block).getListener(levelChunk.level, beacon); - if (gameEventListener != null) { - int i = SectionPos.blockToSectionCoord(beacon.getBlockPos().getY()); - GameEventDispatcher gameEventDispatcher = levelChunk.getEventDispatcher(i); - gameEventDispatcher.unregister(gameEventListener); - if (gameEventDispatcher.isEmpty()) { - try { - ((Int2ObjectMap) fieldGameEventDispatcherSections.get(levelChunk)) - .remove(i); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - } - } - fieldRemove.set(beacon, true); - } - } - methodremoveBlockEntityTicker.invoke(levelChunk, beacon.getBlockPos()); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - } - - static List getEntities(LevelChunk chunk) { - return chunk.level.entityManager.getEntities(chunk.getPos()); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPostProcessor.java deleted file mode 100644 index 0833c6ecb..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPostProcessor.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.fastasyncworldedit.core.queue.IChunk; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.registry.state.PropertyKey; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.Fluids; - -import javax.annotation.Nullable; - -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } - - @SuppressWarnings("deprecation") - @Override - public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) { - boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS; - // The PostProcessor shouldn't be added, but just in case - if (!tickFluid) { - return; - } - PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; - layer: - for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); - if (set == null) { - // No edit means no need to process - continue; - } - char[] get = null; - for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; - char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; - boolean fromGet = false; // Used for liquids - if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { - if (get == null) { - get = getBlocks.load(layer); - } - // If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't - // actually being set - if (get == null) { - continue layer; - } - fromGet = true; - ordinal = replacedOrdinal = get[i]; - } - if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { - continue; - } else if (!fromGet) { // if fromGet, don't do the same again - if (get == null) { - get = getBlocks.load(layer); - } - replacedOrdinal = get[i]; - } - boolean ticking = BlockTypesCache.ticking[ordinal]; - boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; - boolean replacedWasLiquid = false; - BlockState replacedState = null; - if (!ticking) { - // If the block being replaced was not ticking, it cannot be a liquid - if (!replacedWasTicking) { - continue; - } - // If the block being replaced is not fluid, we do not need to worry - if (!(replacedWasLiquid = - (replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) { - continue; - } - } - BlockState state = BlockState.getFromOrdinal(ordinal); - boolean liquid = state.getMaterial().isLiquid(); - int x = i & 15; - int y = (i >> 8) & 15; - int z = (i >> 4) & 15; - BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z); - if (liquid || replacedWasLiquid) { - if (liquid) { - addFluid(getBlocks.serverLevel, state, position); - continue; - } - // If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this - // may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up - // being ticked anyway. We only need it to be "hit" once. - if (!wasAdjacentToWater(get, set, i, x, y, z)) { - continue; - } - addFluid(getBlocks.serverLevel, replacedState, position); - } - } - } - } - - @Nullable - @Override - public Extent construct(final Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } - - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - - @SuppressWarnings("deprecation") - private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { - Fluid type; - if (replacedState.getBlockType() == BlockTypes.LAVA) { - type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA; - } else { - type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER; - } - serverLevel.getLiquidTicks().scheduleTick( - position, - type, - type.getTickDelay(serverLevel) - ); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighter.java deleted file mode 100644 index 8298be6f1..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighter.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.TaskManager; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.MCUtil; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; -import org.apache.logging.log4j.Logger; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.IntConsumer; - -public class PaperweightStarlightRelighter implements Relighter { - - public static final MethodHandle RELIGHT; - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 - private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); - - static { - MethodHandle tmp = null; - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - tmp = lookup.findVirtual( - ThreadedLevelLightEngine.class, - "relight", - MethodType.methodType( - int.class, // return type - // params - Set.class, - Consumer.class, - IntConsumer.class - ) - ); - } catch (NoSuchMethodException | IllegalAccessException e) { - LOGGER.error("Failed to locate 'relight' method in ThreadedLevelLightEngine. Is everything up to date?", e); - } - RELIGHT = tmp; - } - - private final ServerLevel serverLevel; - private final ReentrantLock lock = new ReentrantLock(); - private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); - private final ReentrantLock areaLock = new ReentrantLock(); - private final NMSRelighter delegate; - - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { - this.serverLevel = serverLevel; - this.delegate = new NMSRelighter(queue); - } - - public static boolean isUsable() { - return RELIGHT != null; - } - - @Override - public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { - areaLock.lock(); - try { - long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); - // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? - LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); - } finally { - areaLock.unlock(); - } - return true; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - - /* - * This method is called "recursively", iterating and removing elements - * from the regions linked map. This way, chunks are loaded in batches to avoid - * OOMEs. - */ - @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } - } - - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - int unused = (int) RELIGHT.invokeExact( - serverLevel.getChunkSource().getLightEngine(), - coords, - chunkCallback, // callback per chunk - processCallback // callback for all chunks - ); - } catch (Throwable throwable) { - LOGGER.error("Error occurred on relighting", throwable); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - this.delegate.removeLighting(); - } - - @Override - public void fixBlockLighting() { - fixLightingSafe(true); - } - - @Override - public void fixSkyLighting() { - fixLightingSafe(true); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ReentrantLock getLock() { - return this.lock; - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void close() throws Exception { - fixLightingSafe(true); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighterFactory.java deleted file mode 100644 index 2672c5b62..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightStarlightRelighterFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; - -import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.sk89q.worldedit.world.World; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; - -import javax.annotation.Nonnull; - -public class PaperweightStarlightRelighterFactory implements RelighterFactory { - - @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { - org.bukkit.World w = Bukkit.getWorld(world.getName()); - if (w == null) { - return NullRelighter.INSTANCE; - } - return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue); - } - -} - diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/nbt/PaperweightLazyCompoundTag.java deleted file mode 100644 index 21bc0fe72..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/nbt/PaperweightLazyCompoundTag.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.LazyCompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import net.minecraft.nbt.NumericTag; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -public class PaperweightLazyCompoundTag extends LazyCompoundTag { - - private final Supplier compoundTagSupplier; - private CompoundTag compoundTag; - - public PaperweightLazyCompoundTag(Supplier compoundTagSupplier) { - super(new HashMap<>()); - this.compoundTagSupplier = compoundTagSupplier; - } - - public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) { - this(() -> compoundTag); - } - - public net.minecraft.nbt.CompoundTag get() { - return compoundTagSupplier.get(); - } - - @Override - @SuppressWarnings("unchecked") - public Map getValue() { - if (compoundTag == null) { - compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); - } - return compoundTag.getValue(); - } - - @Override - public CompoundBinaryTag asBinaryTag() { - getValue(); - return compoundTag.asBinaryTag(); - } - - public boolean containsKey(String key) { - return compoundTagSupplier.get().contains(key); - } - - public byte[] getByteArray(String key) { - return compoundTagSupplier.get().getByteArray(key); - } - - public byte getByte(String key) { - return compoundTagSupplier.get().getByte(key); - } - - public double getDouble(String key) { - return compoundTagSupplier.get().getDouble(key); - } - - public double asDouble(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsDouble(); - } - return 0; - } - - public float getFloat(String key) { - return compoundTagSupplier.get().getFloat(key); - } - - public int[] getIntArray(String key) { - return compoundTagSupplier.get().getIntArray(key); - } - - public int getInt(String key) { - return compoundTagSupplier.get().getInt(key); - } - - public int asInt(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsInt(); - } - return 0; - } - - @SuppressWarnings("unchecked") - public List getList(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); - for (net.minecraft.nbt.Tag elem : nbtList) { - if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { - list.add(new PaperweightLazyCompoundTag(compoundTag)); - } else { - list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem)); - } - } - return list; - } - return Collections.emptyList(); - } - - @SuppressWarnings("unchecked") - public ListTag getListTag(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof net.minecraft.nbt.ListTag) { - return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag); - } - return new ListTag(StringTag.class, Collections.emptyList()); - } - - @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { - ListTag listTag = getListTag(key); - if (listTag.getType().equals(listType)) { - return (List) listTag.getValue(); - } else { - return Collections.emptyList(); - } - } - - public long[] getLongArray(String key) { - return compoundTagSupplier.get().getLongArray(key); - } - - public long getLong(String key) { - return compoundTagSupplier.get().getLong(key); - } - - public long asLong(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsLong(); - } - return 0; - } - - public short getShort(String key) { - return compoundTagSupplier.get().getShort(key); - } - - public String getString(String key) { - return compoundTagSupplier.get().getString(key); - } - - @Override - public String toString() { - return compoundTagSupplier.get().toString(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/regen/PaperweightRegen.java deleted file mode 100644 index 3d9694af9..000000000 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/regen/PaperweightRegen.java +++ /dev/null @@ -1,697 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import io.papermc.lib.PaperLib; -import net.minecraft.core.MappedRegistry; -import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.worldgen.biome.Biomes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.LinearCongruentialGenerator; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.biome.OverworldBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.SimpleRandomSource; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; -import net.minecraft.world.level.levelgen.synth.ImprovedNoise; -import net.minecraft.world.level.newbiome.area.Area; -import net.minecraft.world.level.newbiome.area.AreaFactory; -import net.minecraft.world.level.newbiome.context.BigContext; -import net.minecraft.world.level.newbiome.layer.Layer; -import net.minecraft.world.level.newbiome.layer.Layers; -import net.minecraft.world.level.newbiome.layer.traits.PixelTransformer; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_17_R1.CraftServer; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BooleanSupplier; -import java.util.function.LongFunction; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field worldsField; - private static final Field paperConfigField; - private static final Field generateFlatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - worldsField = CraftServer.class.getDeclaredField("worlds"); - worldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - generateFlatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "g")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "e")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C")); - chunkSourceField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureManager structureManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - BiomeProvider biomeProvider = getBiomeProvider(); - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldGenSettings originalOpts = originalWorldData.worldGenSettings(); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataPackConfig() - ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - originalServerWorld.dimensionType(), - new RegenNoOpWorldLoadListener(), - // placeholder. Required for new ChunkProviderServer, but we create and then set it later - newOpts.dimensions().get(levelStemResourceKey).generator(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - environment, - generator, - biomeProvider - ) { - private final Biome singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.get(ResourceLocation.tryParse( - options - .getBiomeType() - .getId())) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig); - } - - //generator - if (originalChunkProvider.getGenerator() instanceof FlatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = (FlatLevelGeneratorSettings) generatorSettingFlatField.get( - originalChunkProvider.getGenerator()); - chunkGenerator = new FlatLevelSource(generatorSettingFlat); - } else if (originalChunkProvider.getGenerator() instanceof NoiseBasedChunkGenerator) { - Supplier generatorSettingBaseSupplier = (Supplier) generatorSettingBaseSupplierField - .get(originalChunkProvider.getGenerator()); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options - .getBiomeType() - .getId()))); - } else { - biomeSource = originalChunkProvider.getGenerator().getBiomeSource(); - if (biomeSource instanceof OverworldBiomeSource) { - biomeSource = fastOverworldBiomeSource(biomeSource); - } - } - chunkGenerator = new NoiseBasedChunkGenerator(biomeSource, seed, generatorSettingBaseSupplier); - } else if (originalChunkProvider.getGenerator() instanceof CustomChunkGenerator) { - chunkGenerator = (ChunkGenerator) delegateField.get(originalChunkProvider.getGenerator()); - } else { - LOGGER.error("Unsupported generator type {}", originalChunkProvider.getGenerator().getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureManager = server.getStructureManager(); - threadedLevelLightEngine = freshChunkProvider.getLightEngine(); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return PaperLib.isPaper() - ? new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, freshWorld) // paper - : new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld); // spigot - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) worldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception { - Field legacyBiomeInitLayerField = OverworldBiomeSource.class.getDeclaredField( - Refraction.pickName("legacyBiomeInitLayer", "i")); - legacyBiomeInitLayerField.setAccessible(true); - Field largeBiomesField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("largeBiomes", "j")); - largeBiomesField.setAccessible(true); - Field biomeRegistryField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("biomes", "k")); - biomeRegistryField.setAccessible(true); - Field areaLazyField = Layer.class.getDeclaredField(Refraction.pickName("area", "b")); - areaLazyField.setAccessible(true); - Method initAreaFactoryMethod = Layers.class.getDeclaredMethod( - Refraction.pickName("getDefaultLayer", "a"), - boolean.class, - int.class, - int.class, - LongFunction.class - ); - initAreaFactoryMethod.setAccessible(true); - - //init new WorldChunkManagerOverworld - boolean legacyBiomeInitLayer = legacyBiomeInitLayerField.getBoolean(biomeSource); - boolean largebiomes = largeBiomesField.getBoolean(biomeSource); - Registry biomeRegistryMojang = (Registry) biomeRegistryField.get(biomeSource); - Registry biomeRegistry; - if (options.hasBiomeType()) { - Biome biome = BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options.getBiomeType().getId())); - biomeRegistry = new MappedRegistry<>( - ResourceKey.createRegistryKey(new ResourceLocation("fawe_biomes")), - Lifecycle.experimental() - ); - ((MappedRegistry) biomeRegistry).registerMapping(0, BuiltinRegistries.BIOME.getResourceKey(biome).get(), biome, - Lifecycle.experimental() - ); - } else { - biomeRegistry = biomeRegistryMojang; - } - - //replace genLayer - AreaFactory factory = (AreaFactory) initAreaFactoryMethod.invoke( - null, - legacyBiomeInitLayer, - largebiomes ? 6 : 4, - 4, - (LongFunction) (salt -> new FastWorldGenContextArea(seed, salt)) - ); - biomeSource = new FastOverworldBiomeSource(biomeRegistry, new FastGenLayer(factory)); - - return biomeSource; - } - - private static class FastOverworldBiomeSource extends BiomeSource { - - private final Registry biomeRegistry; - private final boolean isSingleRegistry; - private final FastGenLayer fastGenLayer; - - public FastOverworldBiomeSource( - Registry biomeRegistry, - FastGenLayer genLayer - ) { - super(biomeRegistry.stream().collect(Collectors.toList())); - this.biomeRegistry = biomeRegistry; - this.isSingleRegistry = biomeRegistry.entrySet().size() == 1; - this.fastGenLayer = genLayer; - } - - @Override - protected Codec codec() { - return OverworldBiomeSource.CODEC; - } - - @Override - public BiomeSource withSeed(final long seed) { - return null; - } - - @Override - public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (this.isSingleRegistry) { - return this.biomeRegistry.byId(0); - } - return this.fastGenLayer.get(this.biomeRegistry, biomeX, biomeZ); - } - - } - - private static class FastWorldGenContextArea implements BigContext { - - private final ConcurrentHashMap sharedAreaMap = new ConcurrentHashMap<>(); - private final ImprovedNoise improvedNoise; - private final long magicrandom; - private final ConcurrentHashMap map = new ConcurrentHashMap<>(); //needed for multithreaded generation - - public FastWorldGenContextArea(long seed, long lconst) { - this.magicrandom = mix(seed, lconst); - this.improvedNoise = new ImprovedNoise(new SimpleRandomSource(seed)); - } - - private static long mix(long seed, long salt) { - long l = LinearCongruentialGenerator.next(salt, salt); - l = LinearCongruentialGenerator.next(l, salt); - l = LinearCongruentialGenerator.next(l, salt); - long m = LinearCongruentialGenerator.next(seed, l); - m = LinearCongruentialGenerator.next(m, l); - m = LinearCongruentialGenerator.next(m, l); - return m; - } - - @Override - public FastAreaLazy createResult(PixelTransformer pixelTransformer) { - return new FastAreaLazy(sharedAreaMap, pixelTransformer); - } - - @Override - public void initRandom(long x, long z) { - long l = this.magicrandom; - l = LinearCongruentialGenerator.next(l, x); - l = LinearCongruentialGenerator.next(l, z); - l = LinearCongruentialGenerator.next(l, x); - l = LinearCongruentialGenerator.next(l, z); - this.map.put(Thread.currentThread().getId(), l); - } - - @Override - public int nextRandom(int y) { - long tid = Thread.currentThread().getId(); - long e = this.map.computeIfAbsent(tid, i -> 0L); - int mod = (int) Math.floorMod(e >> 24L, (long) y); - this.map.put(tid, LinearCongruentialGenerator.next(e, this.magicrandom)); - return mod; - } - - @Override - public ImprovedNoise getBiomeNoise() { - return this.improvedNoise; - } - - } - - private static class FastGenLayer extends Layer { - - private final FastAreaLazy fastAreaLazy; - - public FastGenLayer(AreaFactory factory) { - super(() -> null); - this.fastAreaLazy = factory.make(); - } - - @Override - public Biome get(Registry registry, int x, int z) { - ResourceKey key = Biomes.byId(this.fastAreaLazy.get(x, z)); - if (key == null) { - return registry.get(Biomes.byId(0)); - } - Biome biome = registry.get(key); - if (biome == null) { - return registry.get(Biomes.byId(0)); - } - return biome; - } - - } - - private record FastAreaLazy(ConcurrentHashMap sharedMap, PixelTransformer transformer) implements Area { - - @Override - public int get(int x, int z) { - long zx = ChunkPos.asLong(x, z); - return this.sharedMap.computeIfAbsent(zx, i -> this.transformer.apply(x, z)); - } - - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - // avoid warning on paper - public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, ServerLevel serverLevel) { - super(pos, upgradeData, world, serverLevel); - } - - // compatibility with spigot - public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor) { - super(pos, upgradeData, levelHeightAccessor); - } - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.getName(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks - ); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java deleted file mode 100644 index 84cae3e57..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java +++ /dev/null @@ -1,2943 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.mojang.datafixers.DSL.TypeReference; -import com.mojang.datafixers.DataFixer; -import com.mojang.datafixers.DataFixerBuilder; -import com.mojang.datafixers.schemas.Schema; -import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import net.minecraft.core.Direction; -import net.minecraft.nbt.NbtOps; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.TextComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; -import net.minecraft.util.StringUtil; -import net.minecraft.util.datafix.DataFixers; -import net.minecraft.util.datafix.fixes.References; -import net.minecraft.world.item.DyeColor; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executor; -import java.util.stream.Collectors; -import javax.annotation.Nullable; - -/** - * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) - *

- * We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy - * which is safer, faster and cleaner code. - *

- * The pre DFU code did not fail when the Source version was unknown. - *

- * This class also provides util methods for converting compounds to wrap the update call to - * receive the source version in the compound - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - - private static final NbtOps OPS_NBT = NbtOps.INSTANCE; - private static final int LEGACY_VERSION = 1343; - private static final Map DFU_TO_LEGACY = new HashMap<>(); - private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); - static PaperweightDataConverters INSTANCE; - private static int DATA_VERSION; - - static { - final Map map = OLD_ID_TO_KEY_MAP; - map.put("EntityItem", new ResourceLocation("item")); - map.put("EntityExperienceOrb", new ResourceLocation("xp_orb")); - map.put("EntityAreaEffectCloud", new ResourceLocation("area_effect_cloud")); - map.put("EntityGuardianElder", new ResourceLocation("elder_guardian")); - map.put("EntitySkeletonWither", new ResourceLocation("wither_skeleton")); - map.put("EntitySkeletonStray", new ResourceLocation("stray")); - map.put("EntityEgg", new ResourceLocation("egg")); - map.put("EntityLeash", new ResourceLocation("leash_knot")); - map.put("EntityPainting", new ResourceLocation("painting")); - map.put("EntityTippedArrow", new ResourceLocation("arrow")); - map.put("EntitySnowball", new ResourceLocation("snowball")); - map.put("EntityLargeFireball", new ResourceLocation("fireball")); - map.put("EntitySmallFireball", new ResourceLocation("small_fireball")); - map.put("EntityEnderPearl", new ResourceLocation("ender_pearl")); - map.put("EntityEnderSignal", new ResourceLocation("eye_of_ender_signal")); - map.put("EntityPotion", new ResourceLocation("potion")); - map.put("EntityThrownExpBottle", new ResourceLocation("xp_bottle")); - map.put("EntityItemFrame", new ResourceLocation("item_frame")); - map.put("EntityWitherSkull", new ResourceLocation("wither_skull")); - map.put("EntityTNTPrimed", new ResourceLocation("tnt")); - map.put("EntityFallingBlock", new ResourceLocation("falling_block")); - map.put("EntityFireworks", new ResourceLocation("fireworks_rocket")); - map.put("EntityZombieHusk", new ResourceLocation("husk")); - map.put("EntitySpectralArrow", new ResourceLocation("spectral_arrow")); - map.put("EntityShulkerBullet", new ResourceLocation("shulker_bullet")); - map.put("EntityDragonFireball", new ResourceLocation("dragon_fireball")); - map.put("EntityZombieVillager", new ResourceLocation("zombie_villager")); - map.put("EntityHorseSkeleton", new ResourceLocation("skeleton_horse")); - map.put("EntityHorseZombie", new ResourceLocation("zombie_horse")); - map.put("EntityArmorStand", new ResourceLocation("armor_stand")); - map.put("EntityHorseDonkey", new ResourceLocation("donkey")); - map.put("EntityHorseMule", new ResourceLocation("mule")); - map.put("EntityEvokerFangs", new ResourceLocation("evocation_fangs")); - map.put("EntityEvoker", new ResourceLocation("evocation_illager")); - map.put("EntityVex", new ResourceLocation("vex")); - map.put("EntityVindicator", new ResourceLocation("vindication_illager")); - map.put("EntityIllagerIllusioner", new ResourceLocation("illusion_illager")); - map.put("EntityMinecartCommandBlock", new ResourceLocation("commandblock_minecart")); - map.put("EntityBoat", new ResourceLocation("boat")); - map.put("EntityMinecartRideable", new ResourceLocation("minecart")); - map.put("EntityMinecartChest", new ResourceLocation("chest_minecart")); - map.put("EntityMinecartFurnace", new ResourceLocation("furnace_minecart")); - map.put("EntityMinecartTNT", new ResourceLocation("tnt_minecart")); - map.put("EntityMinecartHopper", new ResourceLocation("hopper_minecart")); - map.put("EntityMinecartMobSpawner", new ResourceLocation("spawner_minecart")); - map.put("EntityCreeper", new ResourceLocation("creeper")); - map.put("EntitySkeleton", new ResourceLocation("skeleton")); - map.put("EntitySpider", new ResourceLocation("spider")); - map.put("EntityGiantZombie", new ResourceLocation("giant")); - map.put("EntityZombie", new ResourceLocation("zombie")); - map.put("EntitySlime", new ResourceLocation("slime")); - map.put("EntityGhast", new ResourceLocation("ghast")); - map.put("EntityPigZombie", new ResourceLocation("zombie_pigman")); - map.put("EntityEnderman", new ResourceLocation("enderman")); - map.put("EntityCaveSpider", new ResourceLocation("cave_spider")); - map.put("EntitySilverfish", new ResourceLocation("silverfish")); - map.put("EntityBlaze", new ResourceLocation("blaze")); - map.put("EntityMagmaCube", new ResourceLocation("magma_cube")); - map.put("EntityEnderDragon", new ResourceLocation("ender_dragon")); - map.put("EntityWither", new ResourceLocation("wither")); - map.put("EntityBat", new ResourceLocation("bat")); - map.put("EntityWitch", new ResourceLocation("witch")); - map.put("EntityEndermite", new ResourceLocation("endermite")); - map.put("EntityGuardian", new ResourceLocation("guardian")); - map.put("EntityShulker", new ResourceLocation("shulker")); - map.put("EntityPig", new ResourceLocation("pig")); - map.put("EntitySheep", new ResourceLocation("sheep")); - map.put("EntityCow", new ResourceLocation("cow")); - map.put("EntityChicken", new ResourceLocation("chicken")); - map.put("EntitySquid", new ResourceLocation("squid")); - map.put("EntityWolf", new ResourceLocation("wolf")); - map.put("EntityMushroomCow", new ResourceLocation("mooshroom")); - map.put("EntitySnowman", new ResourceLocation("snowman")); - map.put("EntityOcelot", new ResourceLocation("ocelot")); - map.put("EntityIronGolem", new ResourceLocation("villager_golem")); - map.put("EntityHorse", new ResourceLocation("horse")); - map.put("EntityRabbit", new ResourceLocation("rabbit")); - map.put("EntityPolarBear", new ResourceLocation("polar_bear")); - map.put("EntityLlama", new ResourceLocation("llama")); - map.put("EntityLlamaSpit", new ResourceLocation("llama_spit")); - map.put("EntityParrot", new ResourceLocation("parrot")); - map.put("EntityVillager", new ResourceLocation("villager")); - map.put("EntityEnderCrystal", new ResourceLocation("ender_crystal")); - map.put("TileEntityFurnace", new ResourceLocation("furnace")); - map.put("TileEntityChest", new ResourceLocation("chest")); - map.put("TileEntityEnderChest", new ResourceLocation("ender_chest")); - map.put("TileEntityRecordPlayer", new ResourceLocation("jukebox")); - map.put("TileEntityDispenser", new ResourceLocation("dispenser")); - map.put("TileEntityDropper", new ResourceLocation("dropper")); - map.put("TileEntitySign", new ResourceLocation("sign")); - map.put("TileEntityMobSpawner", new ResourceLocation("mob_spawner")); - map.put("TileEntityNote", new ResourceLocation("noteblock")); - map.put("TileEntityPiston", new ResourceLocation("piston")); - map.put("TileEntityBrewingStand", new ResourceLocation("brewing_stand")); - map.put("TileEntityEnchantTable", new ResourceLocation("enchanting_table")); - map.put("TileEntityEnderPortal", new ResourceLocation("end_portal")); - map.put("TileEntityBeacon", new ResourceLocation("beacon")); - map.put("TileEntitySkull", new ResourceLocation("skull")); - map.put("TileEntityLightDetector", new ResourceLocation("daylight_detector")); - map.put("TileEntityHopper", new ResourceLocation("hopper")); - map.put("TileEntityComparator", new ResourceLocation("comparator")); - map.put("TileEntityFlowerPot", new ResourceLocation("flower_pot")); - map.put("TileEntityBanner", new ResourceLocation("banner")); - map.put("TileEntityStructure", new ResourceLocation("structure_block")); - map.put("TileEntityEndGateway", new ResourceLocation("end_gateway")); - map.put("TileEntityCommand", new ResourceLocation("command_block")); - map.put("TileEntityShulkerBox", new ResourceLocation("shulker_box")); - map.put("TileEntityBed", new ResourceLocation("bed")); - } - - private final PaperweightAdapter adapter; - private final Map> converters = new EnumMap<>(LegacyType.class); - private final Map> inspectors = new EnumMap<>(LegacyType.class); - // Set on build - private DataFixer fixer; - - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { - super(dataVersion); - DATA_VERSION = dataVersion; - INSTANCE = this; - this.adapter = adapter; - registerConverters(); - registerInspectors(); - } - - private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { - int propIdx = blockState.indexOf('['); - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - if (propIdx < 0) { - tag.putString("Name", blockState); - } else { - tag.putString("Name", blockState.substring(0, propIdx)); - net.minecraft.nbt.CompoundTag propTag = new net.minecraft.nbt.CompoundTag(); - String props = blockState.substring(propIdx + 1, blockState.length() - 1); - String[] propArr = props.split(","); - for (String pair : propArr) { - final String[] split = pair.split("="); - propTag.putString(split[0], split[1]); - } - tag.put("Properties", propTag); - } - return tag; - } - - private static String fixName(String key, int srcVer, TypeReference type) { - return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, net.minecraft.nbt.StringTag.valueOf(key)), srcVer, DATA_VERSION) - .getValue().getAsString(); - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { - return convert(type.getDFUType(), cmp); - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type.getDFUType(), cmp, sourceVer); - } - - public static net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { - return convert(type.getDFUType(), cmp, sourceVer, targetVer); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { - int i = cmp.contains("DataVersion", 99) ? cmp.getInt("DataVersion") : -1; - return convert(type, cmp, i); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type, cmp, sourceVer, DATA_VERSION); - } - - public static net.minecraft.nbt.CompoundTag convert( - TypeReference type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { - if (sourceVer >= targetVer) { - return cmp; - } - return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer - .update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer) - .getValue(); - } - - private static ResourceLocation getKey(String type) { - final ResourceLocation key = OLD_ID_TO_KEY_MAP.get(type); - if (key == null) { - throw new IllegalArgumentException("Unknown mapping for " + type); - } - return key; - } - - private static void convertCompound( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - String key, - int sourceVer, - int targetVer - ) { - cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer)); - } - - private static void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - if (nbttagcompound.contains(key, 10)) { - convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); - } - } - - private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - if (nbttagcompound.contains(key, 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound.getList(key, 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); - } - } - - } - - //FAWE start - CBT > CT - @SuppressWarnings("unchecked") - @Override - public T fixUp(FixType type, T original, int srcVer) { - if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_STATE) { - return (T) fixBlockState((String) original, srcVer); - } else if (type == FixTypes.ITEM_TYPE) { - return (T) fixItemType((String) original, srcVer); - } else if (type == FixTypes.BIOME) { - return (T) fixBiome((String) original, srcVer); - } - return original; - } - - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); - } - //FAWE end - - private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update( - References.BLOCK_STATE, - dynamic, - srcVer, - DATA_VERSION - ).getValue(); - return nbtToState(fixed); - } - - private String nbtToState(net.minecraft.nbt.CompoundTag tagCompound) { - StringBuilder sb = new StringBuilder(); - sb.append(tagCompound.getString("Name")); - if (tagCompound.contains("Properties", 10)) { - sb.append('['); - net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties"); - sb.append(props - .getAllKeys() - .stream() - .map(k -> k + "=" + props.getString(k).replace("\"", "")) - .collect(Collectors.joining(","))); - sb.append(']'); - } - return sb.toString(); - } - - private String fixBiome(String key, int srcVer) { - return fixName(key, srcVer, References.BIOME); - } - - private String fixItemType(String key, int srcVer) { - return fixName(key, srcVer, References.ITEM_NAME); - } - - // Called after fixers are built and ready for FIXING - @Override - public DataFixer build(final Executor executor) { - return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); - } - - private void registerInspector(LegacyType type, DataInspector inspector) { - this.inspectors.computeIfAbsent(type, k -> new ArrayList<>()).add(inspector); - } - - private void registerConverter(LegacyType type, DataConverter converter) { - int version = converter.getDataVersion(); - - List list = this.converters.computeIfAbsent(type, k -> new ArrayList<>()); - if (!list.isEmpty() && list.get(list.size() - 1).getDataVersion() > version) { - for (int j = 0; j < list.size(); ++j) { - if (list.get(j).getDataVersion() > version) { - list.add(j, converter); - break; - } - } - } else { - list.add(converter); - } - } - - private void registerInspectors() { - registerEntityItemList("EntityHorseDonkey", "SaddleItem", "Items"); - registerEntityItemList("EntityHorseMule", "Items"); - registerEntityItemList("EntityMinecartChest", "Items"); - registerEntityItemList("EntityMinecartHopper", "Items"); - registerEntityItemList("EntityVillager", "Inventory"); - registerEntityItemListEquipment("EntityArmorStand"); - registerEntityItemListEquipment("EntityBat"); - registerEntityItemListEquipment("EntityBlaze"); - registerEntityItemListEquipment("EntityCaveSpider"); - registerEntityItemListEquipment("EntityChicken"); - registerEntityItemListEquipment("EntityCow"); - registerEntityItemListEquipment("EntityCreeper"); - registerEntityItemListEquipment("EntityEnderDragon"); - registerEntityItemListEquipment("EntityEnderman"); - registerEntityItemListEquipment("EntityEndermite"); - registerEntityItemListEquipment("EntityEvoker"); - registerEntityItemListEquipment("EntityGhast"); - registerEntityItemListEquipment("EntityGiantZombie"); - registerEntityItemListEquipment("EntityGuardian"); - registerEntityItemListEquipment("EntityGuardianElder"); - registerEntityItemListEquipment("EntityHorse"); - registerEntityItemListEquipment("EntityHorseDonkey"); - registerEntityItemListEquipment("EntityHorseMule"); - registerEntityItemListEquipment("EntityHorseSkeleton"); - registerEntityItemListEquipment("EntityHorseZombie"); - registerEntityItemListEquipment("EntityIronGolem"); - registerEntityItemListEquipment("EntityMagmaCube"); - registerEntityItemListEquipment("EntityMushroomCow"); - registerEntityItemListEquipment("EntityOcelot"); - registerEntityItemListEquipment("EntityPig"); - registerEntityItemListEquipment("EntityPigZombie"); - registerEntityItemListEquipment("EntityRabbit"); - registerEntityItemListEquipment("EntitySheep"); - registerEntityItemListEquipment("EntityShulker"); - registerEntityItemListEquipment("EntitySilverfish"); - registerEntityItemListEquipment("EntitySkeleton"); - registerEntityItemListEquipment("EntitySkeletonStray"); - registerEntityItemListEquipment("EntitySkeletonWither"); - registerEntityItemListEquipment("EntitySlime"); - registerEntityItemListEquipment("EntitySnowman"); - registerEntityItemListEquipment("EntitySpider"); - registerEntityItemListEquipment("EntitySquid"); - registerEntityItemListEquipment("EntityVex"); - registerEntityItemListEquipment("EntityVillager"); - registerEntityItemListEquipment("EntityVindicator"); - registerEntityItemListEquipment("EntityWitch"); - registerEntityItemListEquipment("EntityWither"); - registerEntityItemListEquipment("EntityWolf"); - registerEntityItemListEquipment("EntityZombie"); - registerEntityItemListEquipment("EntityZombieHusk"); - registerEntityItemListEquipment("EntityZombieVillager"); - registerEntityItemSingle("EntityFireworks", "FireworksItem"); - registerEntityItemSingle("EntityHorse", "ArmorItem"); - registerEntityItemSingle("EntityHorse", "SaddleItem"); - registerEntityItemSingle("EntityHorseMule", "SaddleItem"); - registerEntityItemSingle("EntityHorseSkeleton", "SaddleItem"); - registerEntityItemSingle("EntityHorseZombie", "SaddleItem"); - registerEntityItemSingle("EntityItem", "Item"); - registerEntityItemSingle("EntityItemFrame", "Item"); - registerEntityItemSingle("EntityPotion", "Potion"); - - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItem("TileEntityRecordPlayer", "RecordItem")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityBrewingStand", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityChest", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDispenser", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDropper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityFurnace", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityHopper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityShulkerBox", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorMobSpawnerMobs()); - registerInspector(LegacyType.CHUNK, new DataInspectorChunks()); - registerInspector(LegacyType.ENTITY, new DataInspectorCommandBlock()); - registerInspector(LegacyType.ENTITY, new DataInspectorEntityPassengers()); - registerInspector(LegacyType.ENTITY, new DataInspectorMobSpawnerMinecart()); - registerInspector(LegacyType.ENTITY, new DataInspectorVillagers()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorBlockEntity()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorEntity()); - registerInspector(LegacyType.LEVEL, new DataInspectorLevelPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayerVehicle()); - registerInspector(LegacyType.STRUCTURE, new DataInspectorStructure()); - } - - private void registerConverters() { - registerConverter(LegacyType.ENTITY, new DataConverterEquipment()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterSignText()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterMaterialId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterSpawnEgg()); - registerConverter(LegacyType.ENTITY, new DataConverterMinecart()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterMobSpawner()); - registerConverter(LegacyType.ENTITY, new DataConverterUUID()); - registerConverter(LegacyType.ENTITY, new DataConverterHealth()); - registerConverter(LegacyType.ENTITY, new DataConverterSaddle()); - registerConverter(LegacyType.ENTITY, new DataConverterHanging()); - registerConverter(LegacyType.ENTITY, new DataConverterDropChances()); - registerConverter(LegacyType.ENTITY, new DataConverterRiding()); - registerConverter(LegacyType.ENTITY, new DataConverterArmorStand()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBook()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterCookedFish()); - registerConverter(LegacyType.ENTITY, new DataConverterZombie()); - registerConverter(LegacyType.OPTIONS, new DataConverterVBO()); - registerConverter(LegacyType.ENTITY, new DataConverterGuardian()); - registerConverter(LegacyType.ENTITY, new DataConverterSkeleton()); - registerConverter(LegacyType.ENTITY, new DataConverterZombieType()); - registerConverter(LegacyType.ENTITY, new DataConverterHorse()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterTileEntity()); - registerConverter(LegacyType.ENTITY, new DataConverterEntity()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBanner()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionWater()); - registerConverter(LegacyType.ENTITY, new DataConverterShulker()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterShulkerBoxItem()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterShulkerBoxBlock()); - registerConverter(LegacyType.OPTIONS, new DataConverterLang()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterTotem()); - registerConverter(LegacyType.CHUNK, new DataConverterBedBlock()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBedItem()); - } - - private void registerEntityItemList(String type, String... keys) { - registerInspector(LegacyType.ENTITY, new DataInspectorItemList(type, keys)); - } - - private void registerEntityItemSingle(String type, String key) { - registerInspector(LegacyType.ENTITY, new DataInspectorItem(type, key)); - } - - private void registerEntityItemListEquipment(String type) { - registerEntityItemList(type, "ArmorItems", "HandItems"); - } - - public enum LegacyType { - LEVEL(References.LEVEL), - PLAYER(References.PLAYER), - CHUNK(References.CHUNK), - BLOCK_ENTITY(References.BLOCK_ENTITY), - ENTITY(References.ENTITY), - ITEM_INSTANCE(References.ITEM_STACK), - OPTIONS(References.OPTIONS), - STRUCTURE(References.STRUCTURE); - - private final TypeReference type; - - LegacyType(TypeReference type) { - this.type = type; - DFU_TO_LEGACY.put(type.typeName(), this); - } - - public TypeReference getDFUType() { - return type; - } - } - - public interface DataInspector { - - net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); - - } - - public interface DataConverter { - - int getDataVersion(); - - net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); - - } - - private static class DataConverterEquipment implements DataConverter { - - DataConverterEquipment() { - } - - public int getDataVersion() { - return 100; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Equipment", 10); - net.minecraft.nbt.ListTag nbttaglist1; - - if (!nbttaglist.isEmpty() && !cmp.contains("HandItems", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); - nbttaglist1.add(nbttaglist.get(0)); - nbttaglist1.add(new net.minecraft.nbt.CompoundTag()); - cmp.put("HandItems", nbttaglist1); - } - - if (nbttaglist.size() > 1 && !cmp.contains("ArmorItem", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); - nbttaglist1.add(nbttaglist.get(1)); - nbttaglist1.add(nbttaglist.get(2)); - nbttaglist1.add(nbttaglist.get(3)); - nbttaglist1.add(nbttaglist.get(4)); - cmp.put("ArmorItems", nbttaglist1); - } - - cmp.remove("Equipment"); - if (cmp.contains("DropChances", 9)) { - nbttaglist1 = cmp.getList("DropChances", 5); - net.minecraft.nbt.ListTag nbttaglist2; - - if (!cmp.contains("HandDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(0))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(0.0F)); - cmp.put("HandDropChances", nbttaglist2); - } - - if (!cmp.contains("ArmorDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(1))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(2))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(3))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(4))); - cmp.put("ArmorDropChances", nbttaglist2); - } - - cmp.remove("DropChances"); - } - - return cmp; - } - - } - - private static class DataInspectorBlockEntity implements DataInspector { - - private static final Map b = Maps.newHashMap(); - private static final Map c = Maps.newHashMap(); - - static { - Map map = DataInspectorBlockEntity.b; - - map.put("minecraft:furnace", "Furnace"); - map.put("minecraft:lit_furnace", "Furnace"); - map.put("minecraft:chest", "Chest"); - map.put("minecraft:trapped_chest", "Chest"); - map.put("minecraft:ender_chest", "EnderChest"); - map.put("minecraft:jukebox", "RecordPlayer"); - map.put("minecraft:dispenser", "Trap"); - map.put("minecraft:dropper", "Dropper"); - map.put("minecraft:sign", "Sign"); - map.put("minecraft:mob_spawner", "MobSpawner"); - map.put("minecraft:noteblock", "Music"); - map.put("minecraft:brewing_stand", "Cauldron"); - map.put("minecraft:enhanting_table", "EnchantTable"); - map.put("minecraft:command_block", "CommandBlock"); - map.put("minecraft:beacon", "Beacon"); - map.put("minecraft:skull", "Skull"); - map.put("minecraft:daylight_detector", "DLDetector"); - map.put("minecraft:hopper", "Hopper"); - map.put("minecraft:banner", "Banner"); - map.put("minecraft:flower_pot", "FlowerPot"); - map.put("minecraft:repeating_command_block", "CommandBlock"); - map.put("minecraft:chain_command_block", "CommandBlock"); - map.put("minecraft:standing_sign", "Sign"); - map.put("minecraft:wall_sign", "Sign"); - map.put("minecraft:piston_head", "Piston"); - map.put("minecraft:daylight_detector_inverted", "DLDetector"); - map.put("minecraft:unpowered_comparator", "Comparator"); - map.put("minecraft:powered_comparator", "Comparator"); - map.put("minecraft:wall_banner", "Banner"); - map.put("minecraft:standing_banner", "Banner"); - map.put("minecraft:structure_block", "Structure"); - map.put("minecraft:end_portal", "Airportal"); - map.put("minecraft:end_gateway", "EndGateway"); - map.put("minecraft:shield", "Shield"); - map = DataInspectorBlockEntity.c; - map.put("minecraft:furnace", "minecraft:furnace"); - map.put("minecraft:lit_furnace", "minecraft:furnace"); - map.put("minecraft:chest", "minecraft:chest"); - map.put("minecraft:trapped_chest", "minecraft:chest"); - map.put("minecraft:ender_chest", "minecraft:enderchest"); - map.put("minecraft:jukebox", "minecraft:jukebox"); - map.put("minecraft:dispenser", "minecraft:dispenser"); - map.put("minecraft:dropper", "minecraft:dropper"); - map.put("minecraft:sign", "minecraft:sign"); - map.put("minecraft:mob_spawner", "minecraft:mob_spawner"); - map.put("minecraft:noteblock", "minecraft:noteblock"); - map.put("minecraft:brewing_stand", "minecraft:brewing_stand"); - map.put("minecraft:enhanting_table", "minecraft:enchanting_table"); - map.put("minecraft:command_block", "minecraft:command_block"); - map.put("minecraft:beacon", "minecraft:beacon"); - map.put("minecraft:skull", "minecraft:skull"); - map.put("minecraft:daylight_detector", "minecraft:daylight_detector"); - map.put("minecraft:hopper", "minecraft:hopper"); - map.put("minecraft:banner", "minecraft:banner"); - map.put("minecraft:flower_pot", "minecraft:flower_pot"); - map.put("minecraft:repeating_command_block", "minecraft:command_block"); - map.put("minecraft:chain_command_block", "minecraft:command_block"); - map.put("minecraft:shulker_box", "minecraft:shulker_box"); - map.put("minecraft:white_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:orange_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:magenta_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:light_blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:yellow_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:lime_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:pink_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:gray_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:silver_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:cyan_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:purple_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:brown_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:green_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:red_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:black_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:bed", "minecraft:bed"); - map.put("minecraft:standing_sign", "minecraft:sign"); - map.put("minecraft:wall_sign", "minecraft:sign"); - map.put("minecraft:piston_head", "minecraft:piston"); - map.put("minecraft:daylight_detector_inverted", "minecraft:daylight_detector"); - map.put("minecraft:unpowered_comparator", "minecraft:comparator"); - map.put("minecraft:powered_comparator", "minecraft:comparator"); - map.put("minecraft:wall_banner", "minecraft:banner"); - map.put("minecraft:standing_banner", "minecraft:banner"); - map.put("minecraft:structure_block", "minecraft:structure_block"); - map.put("minecraft:end_portal", "minecraft:end_portal"); - map.put("minecraft:end_gateway", "minecraft:end_gateway"); - map.put("minecraft:shield", "minecraft:shield"); - } - - DataInspectorBlockEntity() { - } - - @Nullable - private static String convertEntityId(int i, String s) { - String key = new ResourceLocation(s).toString(); - if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { - return DataInspectorBlockEntity.b.get(key); - } else { - return DataInspectorBlockEntity.c.get(key); - } - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (!cmp.contains("tag", 10)) { - return cmp; - } else { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - String s = cmp.getString("id"); - String s1 = convertEntityId(sourceVer, s); - boolean flag; - - if (s1 == null) { - // CraftBukkit - Remove unnecessary warning (occurs when deserializing a Shulker Box item) - // DataInspectorBlockEntity.a.warn("Unable to resolve BlockEntity for ItemInstance: {}", s); - flag = false; - } else { - flag = !nbttagcompound2.contains("id"); - nbttagcompound2.putString("id", s1); - } - - convert(LegacyType.BLOCK_ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - } - - return cmp; - } - } - } - - private static class DataInspectorEntity implements DataInspector { - - private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); - - DataInspectorEntity() { - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("EntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); - String s = cmp.getString("id"); - String s1; - - if ("minecraft:armor_stand".equals(s)) { - s1 = sourceVer < 515 ? "ArmorStand" : "minecraft:armor_stand"; - } else { - if (!"minecraft:spawn_egg".equals(s)) { - return cmp; - } - - s1 = nbttagcompound2.getString("id"); - } - - boolean flag; - - flag = !nbttagcompound2.contains("id", 8); - nbttagcompound2.putString("id", s1); - - convert(LegacyType.ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - } - - return cmp; - } - - } - - private abstract static class DataInspectorTagged implements DataInspector { - - private final ResourceLocation key; - - DataInspectorTagged(String type) { - this.key = getKey(type); - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (this.key.equals(new ResourceLocation(cmp.getString("id")))) { - cmp = this.inspectChecked(cmp, sourceVer, targetVer); - } - - return cmp; - } - - abstract net.minecraft.nbt.CompoundTag inspectChecked( - net.minecraft.nbt.CompoundTag nbttagcompound, - int sourceVer, - int targetVer - ); - - } - - private static class DataInspectorItemList extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItemList(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String s : this.keys) { - PaperweightDataConverters.convertItems(nbttagcompound, s, sourceVer, targetVer); - } - - return nbttagcompound; - } - - } - - private static class DataInspectorItem extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItem(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String key : this.keys) { - PaperweightDataConverters.convertItem(nbttagcompound, key, sourceVer, targetVer); - } - - return nbttagcompound; - } - - } - - private static class DataConverterMaterialId implements DataConverter { - - private static final String[] materials = new String[2268]; - - static { - materials[1] = "minecraft:stone"; - materials[2] = "minecraft:grass"; - materials[3] = "minecraft:dirt"; - materials[4] = "minecraft:cobblestone"; - materials[5] = "minecraft:planks"; - materials[6] = "minecraft:sapling"; - materials[7] = "minecraft:bedrock"; - materials[8] = "minecraft:flowing_water"; - materials[9] = "minecraft:water"; - materials[10] = "minecraft:flowing_lava"; - materials[11] = "minecraft:lava"; - materials[12] = "minecraft:sand"; - materials[13] = "minecraft:gravel"; - materials[14] = "minecraft:gold_ore"; - materials[15] = "minecraft:iron_ore"; - materials[16] = "minecraft:coal_ore"; - materials[17] = "minecraft:log"; - materials[18] = "minecraft:leaves"; - materials[19] = "minecraft:sponge"; - materials[20] = "minecraft:glass"; - materials[21] = "minecraft:lapis_ore"; - materials[22] = "minecraft:lapis_block"; - materials[23] = "minecraft:dispenser"; - materials[24] = "minecraft:sandstone"; - materials[25] = "minecraft:noteblock"; - materials[27] = "minecraft:golden_rail"; - materials[28] = "minecraft:detector_rail"; - materials[29] = "minecraft:sticky_piston"; - materials[30] = "minecraft:web"; - materials[31] = "minecraft:tallgrass"; - materials[32] = "minecraft:deadbush"; - materials[33] = "minecraft:piston"; - materials[35] = "minecraft:wool"; - materials[37] = "minecraft:yellow_flower"; - materials[38] = "minecraft:red_flower"; - materials[39] = "minecraft:brown_mushroom"; - materials[40] = "minecraft:red_mushroom"; - materials[41] = "minecraft:gold_block"; - materials[42] = "minecraft:iron_block"; - materials[43] = "minecraft:double_stone_slab"; - materials[44] = "minecraft:stone_slab"; - materials[45] = "minecraft:brick_block"; - materials[46] = "minecraft:tnt"; - materials[47] = "minecraft:bookshelf"; - materials[48] = "minecraft:mossy_cobblestone"; - materials[49] = "minecraft:obsidian"; - materials[50] = "minecraft:torch"; - materials[51] = "minecraft:fire"; - materials[52] = "minecraft:mob_spawner"; - materials[53] = "minecraft:oak_stairs"; - materials[54] = "minecraft:chest"; - materials[56] = "minecraft:diamond_ore"; - materials[57] = "minecraft:diamond_block"; - materials[58] = "minecraft:crafting_table"; - materials[60] = "minecraft:farmland"; - materials[61] = "minecraft:furnace"; - materials[62] = "minecraft:lit_furnace"; - materials[65] = "minecraft:ladder"; - materials[66] = "minecraft:rail"; - materials[67] = "minecraft:stone_stairs"; - materials[69] = "minecraft:lever"; - materials[70] = "minecraft:stone_pressure_plate"; - materials[72] = "minecraft:wooden_pressure_plate"; - materials[73] = "minecraft:redstone_ore"; - materials[76] = "minecraft:redstone_torch"; - materials[77] = "minecraft:stone_button"; - materials[78] = "minecraft:snow_layer"; - materials[79] = "minecraft:ice"; - materials[80] = "minecraft:snow"; - materials[81] = "minecraft:cactus"; - materials[82] = "minecraft:clay"; - materials[84] = "minecraft:jukebox"; - materials[85] = "minecraft:fence"; - materials[86] = "minecraft:pumpkin"; - materials[87] = "minecraft:netherrack"; - materials[88] = "minecraft:soul_sand"; - materials[89] = "minecraft:glowstone"; - materials[90] = "minecraft:portal"; - materials[91] = "minecraft:lit_pumpkin"; - materials[95] = "minecraft:stained_glass"; - materials[96] = "minecraft:trapdoor"; - materials[97] = "minecraft:monster_egg"; - materials[98] = "minecraft:stonebrick"; - materials[99] = "minecraft:brown_mushroom_block"; - materials[100] = "minecraft:red_mushroom_block"; - materials[101] = "minecraft:iron_bars"; - materials[102] = "minecraft:glass_pane"; - materials[103] = "minecraft:melon_block"; - materials[106] = "minecraft:vine"; - materials[107] = "minecraft:fence_gate"; - materials[108] = "minecraft:brick_stairs"; - materials[109] = "minecraft:stone_brick_stairs"; - materials[110] = "minecraft:mycelium"; - materials[111] = "minecraft:waterlily"; - materials[112] = "minecraft:nether_brick"; - materials[113] = "minecraft:nether_brick_fence"; - materials[114] = "minecraft:nether_brick_stairs"; - materials[116] = "minecraft:enchanting_table"; - materials[119] = "minecraft:end_portal"; - materials[120] = "minecraft:end_portal_frame"; - materials[121] = "minecraft:end_stone"; - materials[122] = "minecraft:dragon_egg"; - materials[123] = "minecraft:redstone_lamp"; - materials[125] = "minecraft:double_wooden_slab"; - materials[126] = "minecraft:wooden_slab"; - materials[127] = "minecraft:cocoa"; - materials[128] = "minecraft:sandstone_stairs"; - materials[129] = "minecraft:emerald_ore"; - materials[130] = "minecraft:ender_chest"; - materials[131] = "minecraft:tripwire_hook"; - materials[133] = "minecraft:emerald_block"; - materials[134] = "minecraft:spruce_stairs"; - materials[135] = "minecraft:birch_stairs"; - materials[136] = "minecraft:jungle_stairs"; - materials[137] = "minecraft:command_block"; - materials[138] = "minecraft:beacon"; - materials[139] = "minecraft:cobblestone_wall"; - materials[141] = "minecraft:carrots"; - materials[142] = "minecraft:potatoes"; - materials[143] = "minecraft:wooden_button"; - materials[145] = "minecraft:anvil"; - materials[146] = "minecraft:trapped_chest"; - materials[147] = "minecraft:light_weighted_pressure_plate"; - materials[148] = "minecraft:heavy_weighted_pressure_plate"; - materials[151] = "minecraft:daylight_detector"; - materials[152] = "minecraft:redstone_block"; - materials[153] = "minecraft:quartz_ore"; - materials[154] = "minecraft:hopper"; - materials[155] = "minecraft:quartz_block"; - materials[156] = "minecraft:quartz_stairs"; - materials[157] = "minecraft:activator_rail"; - materials[158] = "minecraft:dropper"; - materials[159] = "minecraft:stained_hardened_clay"; - materials[160] = "minecraft:stained_glass_pane"; - materials[161] = "minecraft:leaves2"; - materials[162] = "minecraft:log2"; - materials[163] = "minecraft:acacia_stairs"; - materials[164] = "minecraft:dark_oak_stairs"; - materials[170] = "minecraft:hay_block"; - materials[171] = "minecraft:carpet"; - materials[172] = "minecraft:hardened_clay"; - materials[173] = "minecraft:coal_block"; - materials[174] = "minecraft:packed_ice"; - materials[175] = "minecraft:double_plant"; - materials[256] = "minecraft:iron_shovel"; - materials[257] = "minecraft:iron_pickaxe"; - materials[258] = "minecraft:iron_axe"; - materials[259] = "minecraft:flint_and_steel"; - materials[260] = "minecraft:apple"; - materials[261] = "minecraft:bow"; - materials[262] = "minecraft:arrow"; - materials[263] = "minecraft:coal"; - materials[264] = "minecraft:diamond"; - materials[265] = "minecraft:iron_ingot"; - materials[266] = "minecraft:gold_ingot"; - materials[267] = "minecraft:iron_sword"; - materials[268] = "minecraft:wooden_sword"; - materials[269] = "minecraft:wooden_shovel"; - materials[270] = "minecraft:wooden_pickaxe"; - materials[271] = "minecraft:wooden_axe"; - materials[272] = "minecraft:stone_sword"; - materials[273] = "minecraft:stone_shovel"; - materials[274] = "minecraft:stone_pickaxe"; - materials[275] = "minecraft:stone_axe"; - materials[276] = "minecraft:diamond_sword"; - materials[277] = "minecraft:diamond_shovel"; - materials[278] = "minecraft:diamond_pickaxe"; - materials[279] = "minecraft:diamond_axe"; - materials[280] = "minecraft:stick"; - materials[281] = "minecraft:bowl"; - materials[282] = "minecraft:mushroom_stew"; - materials[283] = "minecraft:golden_sword"; - materials[284] = "minecraft:golden_shovel"; - materials[285] = "minecraft:golden_pickaxe"; - materials[286] = "minecraft:golden_axe"; - materials[287] = "minecraft:string"; - materials[288] = "minecraft:feather"; - materials[289] = "minecraft:gunpowder"; - materials[290] = "minecraft:wooden_hoe"; - materials[291] = "minecraft:stone_hoe"; - materials[292] = "minecraft:iron_hoe"; - materials[293] = "minecraft:diamond_hoe"; - materials[294] = "minecraft:golden_hoe"; - materials[295] = "minecraft:wheat_seeds"; - materials[296] = "minecraft:wheat"; - materials[297] = "minecraft:bread"; - materials[298] = "minecraft:leather_helmet"; - materials[299] = "minecraft:leather_chestplate"; - materials[300] = "minecraft:leather_leggings"; - materials[301] = "minecraft:leather_boots"; - materials[302] = "minecraft:chainmail_helmet"; - materials[303] = "minecraft:chainmail_chestplate"; - materials[304] = "minecraft:chainmail_leggings"; - materials[305] = "minecraft:chainmail_boots"; - materials[306] = "minecraft:iron_helmet"; - materials[307] = "minecraft:iron_chestplate"; - materials[308] = "minecraft:iron_leggings"; - materials[309] = "minecraft:iron_boots"; - materials[310] = "minecraft:diamond_helmet"; - materials[311] = "minecraft:diamond_chestplate"; - materials[312] = "minecraft:diamond_leggings"; - materials[313] = "minecraft:diamond_boots"; - materials[314] = "minecraft:golden_helmet"; - materials[315] = "minecraft:golden_chestplate"; - materials[316] = "minecraft:golden_leggings"; - materials[317] = "minecraft:golden_boots"; - materials[318] = "minecraft:flint"; - materials[319] = "minecraft:porkchop"; - materials[320] = "minecraft:cooked_porkchop"; - materials[321] = "minecraft:painting"; - materials[322] = "minecraft:golden_apple"; - materials[323] = "minecraft:sign"; - materials[324] = "minecraft:wooden_door"; - materials[325] = "minecraft:bucket"; - materials[326] = "minecraft:water_bucket"; - materials[327] = "minecraft:lava_bucket"; - materials[328] = "minecraft:minecart"; - materials[329] = "minecraft:saddle"; - materials[330] = "minecraft:iron_door"; - materials[331] = "minecraft:redstone"; - materials[332] = "minecraft:snowball"; - materials[333] = "minecraft:boat"; - materials[334] = "minecraft:leather"; - materials[335] = "minecraft:milk_bucket"; - materials[336] = "minecraft:brick"; - materials[337] = "minecraft:clay_ball"; - materials[338] = "minecraft:reeds"; - materials[339] = "minecraft:paper"; - materials[340] = "minecraft:book"; - materials[341] = "minecraft:slime_ball"; - materials[342] = "minecraft:chest_minecart"; - materials[343] = "minecraft:furnace_minecart"; - materials[344] = "minecraft:egg"; - materials[345] = "minecraft:compass"; - materials[346] = "minecraft:fishing_rod"; - materials[347] = "minecraft:clock"; - materials[348] = "minecraft:glowstone_dust"; - materials[349] = "minecraft:fish"; - materials[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish - materials[351] = "minecraft:dye"; - materials[352] = "minecraft:bone"; - materials[353] = "minecraft:sugar"; - materials[354] = "minecraft:cake"; - materials[355] = "minecraft:bed"; - materials[356] = "minecraft:repeater"; - materials[357] = "minecraft:cookie"; - materials[358] = "minecraft:filled_map"; - materials[359] = "minecraft:shears"; - materials[360] = "minecraft:melon"; - materials[361] = "minecraft:pumpkin_seeds"; - materials[362] = "minecraft:melon_seeds"; - materials[363] = "minecraft:beef"; - materials[364] = "minecraft:cooked_beef"; - materials[365] = "minecraft:chicken"; - materials[366] = "minecraft:cooked_chicken"; - materials[367] = "minecraft:rotten_flesh"; - materials[368] = "minecraft:ender_pearl"; - materials[369] = "minecraft:blaze_rod"; - materials[370] = "minecraft:ghast_tear"; - materials[371] = "minecraft:gold_nugget"; - materials[372] = "minecraft:nether_wart"; - materials[373] = "minecraft:potion"; - materials[374] = "minecraft:glass_bottle"; - materials[375] = "minecraft:spider_eye"; - materials[376] = "minecraft:fermented_spider_eye"; - materials[377] = "minecraft:blaze_powder"; - materials[378] = "minecraft:magma_cream"; - materials[379] = "minecraft:brewing_stand"; - materials[380] = "minecraft:cauldron"; - materials[381] = "minecraft:ender_eye"; - materials[382] = "minecraft:speckled_melon"; - materials[383] = "minecraft:spawn_egg"; - materials[384] = "minecraft:experience_bottle"; - materials[385] = "minecraft:fire_charge"; - materials[386] = "minecraft:writable_book"; - materials[387] = "minecraft:written_book"; - materials[388] = "minecraft:emerald"; - materials[389] = "minecraft:item_frame"; - materials[390] = "minecraft:flower_pot"; - materials[391] = "minecraft:carrot"; - materials[392] = "minecraft:potato"; - materials[393] = "minecraft:baked_potato"; - materials[394] = "minecraft:poisonous_potato"; - materials[395] = "minecraft:map"; - materials[396] = "minecraft:golden_carrot"; - materials[397] = "minecraft:skull"; - materials[398] = "minecraft:carrot_on_a_stick"; - materials[399] = "minecraft:nether_star"; - materials[400] = "minecraft:pumpkin_pie"; - materials[401] = "minecraft:fireworks"; - materials[402] = "minecraft:firework_charge"; - materials[403] = "minecraft:enchanted_book"; - materials[404] = "minecraft:comparator"; - materials[405] = "minecraft:netherbrick"; - materials[406] = "minecraft:quartz"; - materials[407] = "minecraft:tnt_minecart"; - materials[408] = "minecraft:hopper_minecart"; - materials[417] = "minecraft:iron_horse_armor"; - materials[418] = "minecraft:golden_horse_armor"; - materials[419] = "minecraft:diamond_horse_armor"; - materials[420] = "minecraft:lead"; - materials[421] = "minecraft:name_tag"; - materials[422] = "minecraft:command_block_minecart"; - materials[2256] = "minecraft:record_13"; - materials[2257] = "minecraft:record_cat"; - materials[2258] = "minecraft:record_blocks"; - materials[2259] = "minecraft:record_chirp"; - materials[2260] = "minecraft:record_far"; - materials[2261] = "minecraft:record_mall"; - materials[2262] = "minecraft:record_mellohi"; - materials[2263] = "minecraft:record_stal"; - materials[2264] = "minecraft:record_strad"; - materials[2265] = "minecraft:record_ward"; - materials[2266] = "minecraft:record_11"; - materials[2267] = "minecraft:record_wait"; - // Paper start - materials[409] = "minecraft:prismarine_shard"; - materials[410] = "minecraft:prismarine_crystals"; - materials[411] = "minecraft:rabbit"; - materials[412] = "minecraft:cooked_rabbit"; - materials[413] = "minecraft:rabbit_stew"; - materials[414] = "minecraft:rabbit_foot"; - materials[415] = "minecraft:rabbit_hide"; - materials[416] = "minecraft:armor_stand"; - materials[423] = "minecraft:mutton"; - materials[424] = "minecraft:cooked_mutton"; - materials[425] = "minecraft:banner"; - materials[426] = "minecraft:end_crystal"; - materials[427] = "minecraft:spruce_door"; - materials[428] = "minecraft:birch_door"; - materials[429] = "minecraft:jungle_door"; - materials[430] = "minecraft:acacia_door"; - materials[431] = "minecraft:dark_oak_door"; - materials[432] = "minecraft:chorus_fruit"; - materials[433] = "minecraft:chorus_fruit_popped"; - materials[434] = "minecraft:beetroot"; - materials[435] = "minecraft:beetroot_seeds"; - materials[436] = "minecraft:beetroot_soup"; - materials[437] = "minecraft:dragon_breath"; - materials[438] = "minecraft:splash_potion"; - materials[439] = "minecraft:spectral_arrow"; - materials[440] = "minecraft:tipped_arrow"; - materials[441] = "minecraft:lingering_potion"; - materials[442] = "minecraft:shield"; - materials[443] = "minecraft:elytra"; - materials[444] = "minecraft:spruce_boat"; - materials[445] = "minecraft:birch_boat"; - materials[446] = "minecraft:jungle_boat"; - materials[447] = "minecraft:acacia_boat"; - materials[448] = "minecraft:dark_oak_boat"; - materials[449] = "minecraft:totem_of_undying"; - materials[450] = "minecraft:shulker_shell"; - materials[452] = "minecraft:iron_nugget"; - materials[453] = "minecraft:knowledge_book"; - // Paper end - } - - DataConverterMaterialId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 99)) { - short short0 = cmp.getShort("id"); - - if (short0 > 0 && short0 < materials.length && materials[short0] != null) { - cmp.putString("id", materials[short0]); - } - } - - return cmp; - } - } - - private static class DataConverterArmorStand implements DataConverter { - - DataConverterArmorStand() { - } - - public int getDataVersion() { - return 147; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("ArmorStand".equals(cmp.getString("id")) && cmp.getBoolean("Silent") && !cmp.getBoolean("Marker")) { - cmp.remove("Silent"); - } - - return cmp; - } - - } - - private static class DataConverterBanner implements DataConverter { - - DataConverterBanner() { - } - - public int getDataVersion() { - return 804; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:banner".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - - if (nbttagcompound2.contains("Base", 99)) { - cmp.putShort("Damage", (short) (nbttagcompound2.getShort("Base") & 15)); - if (nbttagcompound1.contains("display", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); - - if (nbttagcompound3.contains("Lore", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); - - if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0))) { - return cmp; - } - } - } - - nbttagcompound2.remove("Base"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - } - } - } - - return cmp; - } - - } - - private static class DataConverterPotionId implements DataConverter { - - private static final String[] potions = new String[128]; - - static { - DataConverterPotionId.potions[0] = "minecraft:water"; - DataConverterPotionId.potions[1] = "minecraft:regeneration"; - DataConverterPotionId.potions[2] = "minecraft:swiftness"; - DataConverterPotionId.potions[3] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[4] = "minecraft:poison"; - DataConverterPotionId.potions[5] = "minecraft:healing"; - DataConverterPotionId.potions[6] = "minecraft:night_vision"; - DataConverterPotionId.potions[7] = null; - DataConverterPotionId.potions[8] = "minecraft:weakness"; - DataConverterPotionId.potions[9] = "minecraft:strength"; - DataConverterPotionId.potions[10] = "minecraft:slowness"; - DataConverterPotionId.potions[11] = "minecraft:leaping"; - DataConverterPotionId.potions[12] = "minecraft:harming"; - DataConverterPotionId.potions[13] = "minecraft:water_breathing"; - DataConverterPotionId.potions[14] = "minecraft:invisibility"; - DataConverterPotionId.potions[15] = null; - DataConverterPotionId.potions[16] = "minecraft:awkward"; - DataConverterPotionId.potions[17] = "minecraft:regeneration"; - DataConverterPotionId.potions[18] = "minecraft:swiftness"; - DataConverterPotionId.potions[19] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[20] = "minecraft:poison"; - DataConverterPotionId.potions[21] = "minecraft:healing"; - DataConverterPotionId.potions[22] = "minecraft:night_vision"; - DataConverterPotionId.potions[23] = null; - DataConverterPotionId.potions[24] = "minecraft:weakness"; - DataConverterPotionId.potions[25] = "minecraft:strength"; - DataConverterPotionId.potions[26] = "minecraft:slowness"; - DataConverterPotionId.potions[27] = "minecraft:leaping"; - DataConverterPotionId.potions[28] = "minecraft:harming"; - DataConverterPotionId.potions[29] = "minecraft:water_breathing"; - DataConverterPotionId.potions[30] = "minecraft:invisibility"; - DataConverterPotionId.potions[31] = null; - DataConverterPotionId.potions[32] = "minecraft:thick"; - DataConverterPotionId.potions[33] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[34] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[35] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[36] = "minecraft:strong_poison"; - DataConverterPotionId.potions[37] = "minecraft:strong_healing"; - DataConverterPotionId.potions[38] = "minecraft:night_vision"; - DataConverterPotionId.potions[39] = null; - DataConverterPotionId.potions[40] = "minecraft:weakness"; - DataConverterPotionId.potions[41] = "minecraft:strong_strength"; - DataConverterPotionId.potions[42] = "minecraft:slowness"; - DataConverterPotionId.potions[43] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[44] = "minecraft:strong_harming"; - DataConverterPotionId.potions[45] = "minecraft:water_breathing"; - DataConverterPotionId.potions[46] = "minecraft:invisibility"; - DataConverterPotionId.potions[47] = null; - DataConverterPotionId.potions[48] = null; - DataConverterPotionId.potions[49] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[50] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[51] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[52] = "minecraft:strong_poison"; - DataConverterPotionId.potions[53] = "minecraft:strong_healing"; - DataConverterPotionId.potions[54] = "minecraft:night_vision"; - DataConverterPotionId.potions[55] = null; - DataConverterPotionId.potions[56] = "minecraft:weakness"; - DataConverterPotionId.potions[57] = "minecraft:strong_strength"; - DataConverterPotionId.potions[58] = "minecraft:slowness"; - DataConverterPotionId.potions[59] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[60] = "minecraft:strong_harming"; - DataConverterPotionId.potions[61] = "minecraft:water_breathing"; - DataConverterPotionId.potions[62] = "minecraft:invisibility"; - DataConverterPotionId.potions[63] = null; - DataConverterPotionId.potions[64] = "minecraft:mundane"; - DataConverterPotionId.potions[65] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[66] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[67] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[68] = "minecraft:long_poison"; - DataConverterPotionId.potions[69] = "minecraft:healing"; - DataConverterPotionId.potions[70] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[71] = null; - DataConverterPotionId.potions[72] = "minecraft:long_weakness"; - DataConverterPotionId.potions[73] = "minecraft:long_strength"; - DataConverterPotionId.potions[74] = "minecraft:long_slowness"; - DataConverterPotionId.potions[75] = "minecraft:long_leaping"; - DataConverterPotionId.potions[76] = "minecraft:harming"; - DataConverterPotionId.potions[77] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[78] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[79] = null; - DataConverterPotionId.potions[80] = "minecraft:awkward"; - DataConverterPotionId.potions[81] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[82] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[83] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[84] = "minecraft:long_poison"; - DataConverterPotionId.potions[85] = "minecraft:healing"; - DataConverterPotionId.potions[86] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[87] = null; - DataConverterPotionId.potions[88] = "minecraft:long_weakness"; - DataConverterPotionId.potions[89] = "minecraft:long_strength"; - DataConverterPotionId.potions[90] = "minecraft:long_slowness"; - DataConverterPotionId.potions[91] = "minecraft:long_leaping"; - DataConverterPotionId.potions[92] = "minecraft:harming"; - DataConverterPotionId.potions[93] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[94] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[95] = null; - DataConverterPotionId.potions[96] = "minecraft:thick"; - DataConverterPotionId.potions[97] = "minecraft:regeneration"; - DataConverterPotionId.potions[98] = "minecraft:swiftness"; - DataConverterPotionId.potions[99] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[100] = "minecraft:poison"; - DataConverterPotionId.potions[101] = "minecraft:strong_healing"; - DataConverterPotionId.potions[102] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[103] = null; - DataConverterPotionId.potions[104] = "minecraft:long_weakness"; - DataConverterPotionId.potions[105] = "minecraft:strength"; - DataConverterPotionId.potions[106] = "minecraft:long_slowness"; - DataConverterPotionId.potions[107] = "minecraft:leaping"; - DataConverterPotionId.potions[108] = "minecraft:strong_harming"; - DataConverterPotionId.potions[109] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[110] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[111] = null; - DataConverterPotionId.potions[112] = null; - DataConverterPotionId.potions[113] = "minecraft:regeneration"; - DataConverterPotionId.potions[114] = "minecraft:swiftness"; - DataConverterPotionId.potions[115] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[116] = "minecraft:poison"; - DataConverterPotionId.potions[117] = "minecraft:strong_healing"; - DataConverterPotionId.potions[118] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[119] = null; - DataConverterPotionId.potions[120] = "minecraft:long_weakness"; - DataConverterPotionId.potions[121] = "minecraft:strength"; - DataConverterPotionId.potions[122] = "minecraft:long_slowness"; - DataConverterPotionId.potions[123] = "minecraft:leaping"; - DataConverterPotionId.potions[124] = "minecraft:strong_harming"; - DataConverterPotionId.potions[125] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[126] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[127] = null; - } - - DataConverterPotionId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:potion".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - short short0 = cmp.getShort("Damage"); - - if (!nbttagcompound1.contains("Potion", 8)) { - String s = DataConverterPotionId.potions[short0 & 127]; - - nbttagcompound1.putString("Potion", s == null ? "minecraft:water" : s); - cmp.put("tag", nbttagcompound1); - if ((short0 & 16384) == 16384) { - cmp.putString("id", "minecraft:splash_potion"); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - } - - private static class DataConverterSpawnEgg implements DataConverter { - - private static final String[] eggs = new String[256]; - - static { - - DataConverterSpawnEgg.eggs[1] = "Item"; - DataConverterSpawnEgg.eggs[2] = "XPOrb"; - DataConverterSpawnEgg.eggs[7] = "ThrownEgg"; - DataConverterSpawnEgg.eggs[8] = "LeashKnot"; - DataConverterSpawnEgg.eggs[9] = "Painting"; - DataConverterSpawnEgg.eggs[10] = "Arrow"; - DataConverterSpawnEgg.eggs[11] = "Snowball"; - DataConverterSpawnEgg.eggs[12] = "Fireball"; - DataConverterSpawnEgg.eggs[13] = "SmallFireball"; - DataConverterSpawnEgg.eggs[14] = "ThrownEnderpearl"; - DataConverterSpawnEgg.eggs[15] = "EyeOfEnderSignal"; - DataConverterSpawnEgg.eggs[16] = "ThrownPotion"; - DataConverterSpawnEgg.eggs[17] = "ThrownExpBottle"; - DataConverterSpawnEgg.eggs[18] = "ItemFrame"; - DataConverterSpawnEgg.eggs[19] = "WitherSkull"; - DataConverterSpawnEgg.eggs[20] = "PrimedTnt"; - DataConverterSpawnEgg.eggs[21] = "FallingSand"; - DataConverterSpawnEgg.eggs[22] = "FireworksRocketEntity"; - DataConverterSpawnEgg.eggs[23] = "TippedArrow"; - DataConverterSpawnEgg.eggs[24] = "SpectralArrow"; - DataConverterSpawnEgg.eggs[25] = "ShulkerBullet"; - DataConverterSpawnEgg.eggs[26] = "DragonFireball"; - DataConverterSpawnEgg.eggs[30] = "ArmorStand"; - DataConverterSpawnEgg.eggs[41] = "Boat"; - DataConverterSpawnEgg.eggs[42] = "MinecartRideable"; - DataConverterSpawnEgg.eggs[43] = "MinecartChest"; - DataConverterSpawnEgg.eggs[44] = "MinecartFurnace"; - DataConverterSpawnEgg.eggs[45] = "MinecartTNT"; - DataConverterSpawnEgg.eggs[46] = "MinecartHopper"; - DataConverterSpawnEgg.eggs[47] = "MinecartSpawner"; - DataConverterSpawnEgg.eggs[40] = "MinecartCommandBlock"; - DataConverterSpawnEgg.eggs[48] = "Mob"; - DataConverterSpawnEgg.eggs[49] = "Monster"; - DataConverterSpawnEgg.eggs[50] = "Creeper"; - DataConverterSpawnEgg.eggs[51] = "Skeleton"; - DataConverterSpawnEgg.eggs[52] = "Spider"; - DataConverterSpawnEgg.eggs[53] = "Giant"; - DataConverterSpawnEgg.eggs[54] = "Zombie"; - DataConverterSpawnEgg.eggs[55] = "Slime"; - DataConverterSpawnEgg.eggs[56] = "Ghast"; - DataConverterSpawnEgg.eggs[57] = "PigZombie"; - DataConverterSpawnEgg.eggs[58] = "Enderman"; - DataConverterSpawnEgg.eggs[59] = "CaveSpider"; - DataConverterSpawnEgg.eggs[60] = "Silverfish"; - DataConverterSpawnEgg.eggs[61] = "Blaze"; - DataConverterSpawnEgg.eggs[62] = "LavaSlime"; - DataConverterSpawnEgg.eggs[63] = "EnderDragon"; - DataConverterSpawnEgg.eggs[64] = "WitherBoss"; - DataConverterSpawnEgg.eggs[65] = "Bat"; - DataConverterSpawnEgg.eggs[66] = "Witch"; - DataConverterSpawnEgg.eggs[67] = "Endermite"; - DataConverterSpawnEgg.eggs[68] = "Guardian"; - DataConverterSpawnEgg.eggs[69] = "Shulker"; - DataConverterSpawnEgg.eggs[90] = "Pig"; - DataConverterSpawnEgg.eggs[91] = "Sheep"; - DataConverterSpawnEgg.eggs[92] = "Cow"; - DataConverterSpawnEgg.eggs[93] = "Chicken"; - DataConverterSpawnEgg.eggs[94] = "Squid"; - DataConverterSpawnEgg.eggs[95] = "Wolf"; - DataConverterSpawnEgg.eggs[96] = "MushroomCow"; - DataConverterSpawnEgg.eggs[97] = "SnowMan"; - DataConverterSpawnEgg.eggs[98] = "Ozelot"; - DataConverterSpawnEgg.eggs[99] = "VillagerGolem"; - DataConverterSpawnEgg.eggs[100] = "EntityHorse"; - DataConverterSpawnEgg.eggs[101] = "Rabbit"; - DataConverterSpawnEgg.eggs[120] = "Villager"; - DataConverterSpawnEgg.eggs[200] = "EnderCrystal"; - } - - DataConverterSpawnEgg() { - } - - public int getDataVersion() { - return 105; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); - short short0 = cmp.getShort("Damage"); - - if (!nbttagcompound2.contains("id", 8)) { - String s = DataConverterSpawnEgg.eggs[short0 & 255]; - - if (s != null) { - nbttagcompound2.putString("id", s); - nbttagcompound1.put("EntityTag", nbttagcompound2); - cmp.put("tag", nbttagcompound1); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - } - - private static class DataConverterMinecart implements DataConverter { - - private static final List a = Lists.newArrayList( - "MinecartRideable", - "MinecartChest", - "MinecartFurnace", - "MinecartTNT", - "MinecartSpawner", - "MinecartHopper", - "MinecartCommandBlock" - ); - - DataConverterMinecart() { - } - - public int getDataVersion() { - return 106; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Minecart".equals(cmp.getString("id"))) { - String s = "MinecartRideable"; - int i = cmp.getInt("Type"); - - if (i > 0 && i < DataConverterMinecart.a.size()) { - s = DataConverterMinecart.a.get(i); - } - - cmp.putString("id", s); - cmp.remove("Type"); - } - - return cmp; - } - - } - - private static class DataConverterMobSpawner implements DataConverter { - - DataConverterMobSpawner() { - } - - public int getDataVersion() { - return 107; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (!"MobSpawner".equals(cmp.getString("id"))) { - return cmp; - } else { - if (cmp.contains("EntityId", 8)) { - String s = cmp.getString("EntityId"); - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); - - nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); - cmp.put("SpawnData", nbttagcompound1); - cmp.remove("EntityId"); - } - - if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); - - for (int i = 0; i < nbttaglist.size(); ++i) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); - - if (nbttagcompound2.contains("Type", 8)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); - - nbttagcompound3.putString("id", nbttagcompound2.getString("Type")); - nbttagcompound2.put("Entity", nbttagcompound3); - nbttagcompound2.remove("Type"); - nbttagcompound2.remove("Properties"); - } - } - } - - return cmp; - } - } - - } - - private static class DataConverterUUID implements DataConverter { - - DataConverterUUID() { - } - - public int getDataVersion() { - return 108; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("UUID", 8)) { - cmp.putUUID("UUID", UUID.fromString(cmp.getString("UUID"))); - } - - return cmp; - } - - } - - private static class DataConverterHealth implements DataConverter { - - private static final Set a = Sets.newHashSet( - "ArmorStand", - "Bat", - "Blaze", - "CaveSpider", - "Chicken", - "Cow", - "Creeper", - "EnderDragon", - "Enderman", - "Endermite", - "EntityHorse", - "Ghast", - "Giant", - "Guardian", - "LavaSlime", - "MushroomCow", - "Ozelot", - "Pig", - "PigZombie", - "Rabbit", - "Sheep", - "Shulker", - "Silverfish", - "Skeleton", - "Slime", - "SnowMan", - "Spider", - "Squid", - "Villager", - "VillagerGolem", - "Witch", - "WitherBoss", - "Wolf", - "Zombie" - ); - - DataConverterHealth() { - } - - public int getDataVersion() { - return 109; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (DataConverterHealth.a.contains(cmp.getString("id"))) { - float f; - - if (cmp.contains("HealF", 99)) { - f = cmp.getFloat("HealF"); - cmp.remove("HealF"); - } else { - if (!cmp.contains("Health", 99)) { - return cmp; - } - - f = cmp.getFloat("Health"); - } - - cmp.putFloat("Health", f); - } - - return cmp; - } - - } - - private static class DataConverterSaddle implements DataConverter { - - DataConverterSaddle() { - } - - public int getDataVersion() { - return 110; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id")) && !cmp.contains("SaddleItem", 10) && cmp.getBoolean("Saddle")) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound1.putString("id", "minecraft:saddle"); - nbttagcompound1.putByte("Count", (byte) 1); - nbttagcompound1.putShort("Damage", (short) 0); - cmp.put("SaddleItem", nbttagcompound1); - cmp.remove("Saddle"); - } - - return cmp; - } - - } - - private static class DataConverterHanging implements DataConverter { - - DataConverterHanging() { - } - - public int getDataVersion() { - return 111; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - boolean flag = "Painting".equals(s); - boolean flag1 = "ItemFrame".equals(s); - - if ((flag || flag1) && !cmp.contains("Facing", 99)) { - Direction enumdirection; - - if (cmp.contains("Direction", 99)) { - enumdirection = Direction.from2DDataValue(cmp.getByte("Direction")); - cmp.putInt("TileX", cmp.getInt("TileX") + enumdirection.getStepX()); - cmp.putInt("TileY", cmp.getInt("TileY") + enumdirection.getStepY()); - cmp.putInt("TileZ", cmp.getInt("TileZ") + enumdirection.getStepZ()); - cmp.remove("Direction"); - if (flag1 && cmp.contains("ItemRotation", 99)) { - cmp.putByte("ItemRotation", (byte) (cmp.getByte("ItemRotation") * 2)); - } - } else { - enumdirection = Direction.from2DDataValue(cmp.getByte("Dir")); - cmp.remove("Dir"); - } - - cmp.putByte("Facing", (byte) enumdirection.get2DDataValue()); - } - - return cmp; - } - - } - - private static class DataConverterDropChances implements DataConverter { - - DataConverterDropChances() { - } - - public int getDataVersion() { - return 113; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist; - - if (cmp.contains("HandDropChances", 9)) { - nbttaglist = cmp.getList("HandDropChances", 5); - if (nbttaglist.size() == 2 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F) { - cmp.remove("HandDropChances"); - } - } - - if (cmp.contains("ArmorDropChances", 9)) { - nbttaglist = cmp.getList("ArmorDropChances", 5); - if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat( - 2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { - cmp.remove("ArmorDropChances"); - } - } - - return cmp; - } - - } - - private static class DataConverterRiding implements DataConverter { - - DataConverterRiding() { - } - - public int getDataVersion() { - return 135; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - while (cmp.contains("Riding", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = this.b(cmp); - - this.convert(cmp, nbttagcompound1); - cmp = nbttagcompound1; - } - - return cmp; - } - - protected void convert(net.minecraft.nbt.CompoundTag nbttagcompound, net.minecraft.nbt.CompoundTag nbttagcompound1) { - net.minecraft.nbt.ListTag nbttaglist = new net.minecraft.nbt.ListTag(); - - nbttaglist.add(nbttagcompound); - nbttagcompound1.put("Passengers", nbttaglist); - } - - protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagcompound) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); - - nbttagcompound.remove("Riding"); - return nbttagcompound1; - } - - } - - private static class DataConverterBook implements DataConverter { - - DataConverterBook() { - } - - public int getDataVersion() { - return 165; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:written_book".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("pages", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("pages", 8); - - for (int i = 0; i < nbttaglist.size(); ++i) { - String s = nbttaglist.getString(i); - Component object = null; - - if (!"null".equals(s) && !StringUtil.isNullOrEmpty(s)) { - if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) { - object = new TextComponent(s); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); - if (object == null) { - object = new TextComponent(""); - } - } catch (JsonParseException ignored) { - } - - if (object == null) { - try { - object = Component.Serializer.fromJson(s); - } catch (JsonParseException ignored) { - } - } - - if (object == null) { - try { - object = Component.Serializer.fromJsonLenient(s); - } catch (JsonParseException ignored) { - } - } - - if (object == null) { - object = new TextComponent(s); - } - } - } else { - object = new TextComponent(""); - } - - nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); - } - - nbttagcompound1.put("pages", nbttaglist); - } - } - - return cmp; - } - - } - - private static class DataConverterCookedFish implements DataConverter { - - private static final ResourceLocation a = new ResourceLocation("cooked_fished"); - - DataConverterCookedFish() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(new ResourceLocation(cmp.getString("id")))) { - cmp.putString("id", "minecraft:cooked_fish"); - } - - return cmp; - } - - } - - private static class DataConverterZombie implements DataConverter { - - private static final Random a = new Random(); - - DataConverterZombie() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id")) && cmp.getBoolean("IsVillager")) { - if (!cmp.contains("ZombieType", 99)) { - int i = -1; - - if (cmp.contains("VillagerProfession", 99)) { - try { - i = this.convert(cmp.getInt("VillagerProfession")); - } catch (RuntimeException ignored) { - } - } - - if (i == -1) { - i = this.convert(DataConverterZombie.a.nextInt(6)); - } - - cmp.putInt("ZombieType", i); - } - - cmp.remove("IsVillager"); - } - - return cmp; - } - - private int convert(int i) { - return i >= 0 && i < 6 ? i : -1; - } - - } - - private static class DataConverterVBO implements DataConverter { - - DataConverterVBO() { - } - - public int getDataVersion() { - return 505; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.putString("useVbo", "true"); - return cmp; - } - - } - - private static class DataConverterGuardian implements DataConverter { - - DataConverterGuardian() { - } - - public int getDataVersion() { - return 700; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Guardian".equals(cmp.getString("id"))) { - if (cmp.getBoolean("Elder")) { - cmp.putString("id", "ElderGuardian"); - } - - cmp.remove("Elder"); - } - - return cmp; - } - - } - - private static class DataConverterSkeleton implements DataConverter { - - DataConverterSkeleton() { - } - - public int getDataVersion() { - return 701; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - - if ("Skeleton".equals(s)) { - int i = cmp.getInt("SkeletonType"); - - if (i == 1) { - cmp.putString("id", "WitherSkeleton"); - } else if (i == 2) { - cmp.putString("id", "Stray"); - } - - cmp.remove("SkeletonType"); - } - - return cmp; - } - - } - - private static class DataConverterZombieType implements DataConverter { - - DataConverterZombieType() { - } - - public int getDataVersion() { - return 702; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id"))) { - int i = cmp.getInt("ZombieType"); - - switch (i) { - case 0: - default: - break; - - case 1: - case 2: - case 3: - case 4: - case 5: - cmp.putString("id", "ZombieVillager"); - cmp.putInt("Profession", i - 1); - break; - - case 6: - cmp.putString("id", "Husk"); - } - - cmp.remove("ZombieType"); - } - - return cmp; - } - - } - - private static class DataConverterHorse implements DataConverter { - - DataConverterHorse() { - } - - public int getDataVersion() { - return 703; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id"))) { - int i = cmp.getInt("Type"); - - switch (i) { - case 0: - default: - cmp.putString("id", "Horse"); - break; - - case 1: - cmp.putString("id", "Donkey"); - break; - - case 2: - cmp.putString("id", "Mule"); - break; - - case 3: - cmp.putString("id", "ZombieHorse"); - break; - - case 4: - cmp.putString("id", "SkeletonHorse"); - } - - cmp.remove("Type"); - } - - return cmp; - } - - } - - private static class DataConverterTileEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - static { - DataConverterTileEntity.a.put("Airportal", "minecraft:end_portal"); - DataConverterTileEntity.a.put("Banner", "minecraft:banner"); - DataConverterTileEntity.a.put("Beacon", "minecraft:beacon"); - DataConverterTileEntity.a.put("Cauldron", "minecraft:brewing_stand"); - DataConverterTileEntity.a.put("Chest", "minecraft:chest"); - DataConverterTileEntity.a.put("Comparator", "minecraft:comparator"); - DataConverterTileEntity.a.put("Control", "minecraft:command_block"); - DataConverterTileEntity.a.put("DLDetector", "minecraft:daylight_detector"); - DataConverterTileEntity.a.put("Dropper", "minecraft:dropper"); - DataConverterTileEntity.a.put("EnchantTable", "minecraft:enchanting_table"); - DataConverterTileEntity.a.put("EndGateway", "minecraft:end_gateway"); - DataConverterTileEntity.a.put("EnderChest", "minecraft:ender_chest"); - DataConverterTileEntity.a.put("FlowerPot", "minecraft:flower_pot"); - DataConverterTileEntity.a.put("Furnace", "minecraft:furnace"); - DataConverterTileEntity.a.put("Hopper", "minecraft:hopper"); - DataConverterTileEntity.a.put("MobSpawner", "minecraft:mob_spawner"); - DataConverterTileEntity.a.put("Music", "minecraft:noteblock"); - DataConverterTileEntity.a.put("Piston", "minecraft:piston"); - DataConverterTileEntity.a.put("RecordPlayer", "minecraft:jukebox"); - DataConverterTileEntity.a.put("Sign", "minecraft:sign"); - DataConverterTileEntity.a.put("Skull", "minecraft:skull"); - DataConverterTileEntity.a.put("Structure", "minecraft:structure_block"); - DataConverterTileEntity.a.put("Trap", "minecraft:dispenser"); - } - - DataConverterTileEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterTileEntity.a.get(cmp.getString("id")); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - } - - private static class DataConverterEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - static { - DataConverterEntity.a.put("AreaEffectCloud", "minecraft:area_effect_cloud"); - DataConverterEntity.a.put("ArmorStand", "minecraft:armor_stand"); - DataConverterEntity.a.put("Arrow", "minecraft:arrow"); - DataConverterEntity.a.put("Bat", "minecraft:bat"); - DataConverterEntity.a.put("Blaze", "minecraft:blaze"); - DataConverterEntity.a.put("Boat", "minecraft:boat"); - DataConverterEntity.a.put("CaveSpider", "minecraft:cave_spider"); - DataConverterEntity.a.put("Chicken", "minecraft:chicken"); - DataConverterEntity.a.put("Cow", "minecraft:cow"); - DataConverterEntity.a.put("Creeper", "minecraft:creeper"); - DataConverterEntity.a.put("Donkey", "minecraft:donkey"); - DataConverterEntity.a.put("DragonFireball", "minecraft:dragon_fireball"); - DataConverterEntity.a.put("ElderGuardian", "minecraft:elder_guardian"); - DataConverterEntity.a.put("EnderCrystal", "minecraft:ender_crystal"); - DataConverterEntity.a.put("EnderDragon", "minecraft:ender_dragon"); - DataConverterEntity.a.put("Enderman", "minecraft:enderman"); - DataConverterEntity.a.put("Endermite", "minecraft:endermite"); - DataConverterEntity.a.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal"); - DataConverterEntity.a.put("FallingSand", "minecraft:falling_block"); - DataConverterEntity.a.put("Fireball", "minecraft:fireball"); - DataConverterEntity.a.put("FireworksRocketEntity", "minecraft:fireworks_rocket"); - DataConverterEntity.a.put("Ghast", "minecraft:ghast"); - DataConverterEntity.a.put("Giant", "minecraft:giant"); - DataConverterEntity.a.put("Guardian", "minecraft:guardian"); - DataConverterEntity.a.put("Horse", "minecraft:horse"); - DataConverterEntity.a.put("Husk", "minecraft:husk"); - DataConverterEntity.a.put("Item", "minecraft:item"); - DataConverterEntity.a.put("ItemFrame", "minecraft:item_frame"); - DataConverterEntity.a.put("LavaSlime", "minecraft:magma_cube"); - DataConverterEntity.a.put("LeashKnot", "minecraft:leash_knot"); - DataConverterEntity.a.put("MinecartChest", "minecraft:chest_minecart"); - DataConverterEntity.a.put("MinecartCommandBlock", "minecraft:commandblock_minecart"); - DataConverterEntity.a.put("MinecartFurnace", "minecraft:furnace_minecart"); - DataConverterEntity.a.put("MinecartHopper", "minecraft:hopper_minecart"); - DataConverterEntity.a.put("MinecartRideable", "minecraft:minecart"); - DataConverterEntity.a.put("MinecartSpawner", "minecraft:spawner_minecart"); - DataConverterEntity.a.put("MinecartTNT", "minecraft:tnt_minecart"); - DataConverterEntity.a.put("Mule", "minecraft:mule"); - DataConverterEntity.a.put("MushroomCow", "minecraft:mooshroom"); - DataConverterEntity.a.put("Ozelot", "minecraft:ocelot"); - DataConverterEntity.a.put("Painting", "minecraft:painting"); - DataConverterEntity.a.put("Pig", "minecraft:pig"); - DataConverterEntity.a.put("PigZombie", "minecraft:zombie_pigman"); - DataConverterEntity.a.put("PolarBear", "minecraft:polar_bear"); - DataConverterEntity.a.put("PrimedTnt", "minecraft:tnt"); - DataConverterEntity.a.put("Rabbit", "minecraft:rabbit"); - DataConverterEntity.a.put("Sheep", "minecraft:sheep"); - DataConverterEntity.a.put("Shulker", "minecraft:shulker"); - DataConverterEntity.a.put("ShulkerBullet", "minecraft:shulker_bullet"); - DataConverterEntity.a.put("Silverfish", "minecraft:silverfish"); - DataConverterEntity.a.put("Skeleton", "minecraft:skeleton"); - DataConverterEntity.a.put("SkeletonHorse", "minecraft:skeleton_horse"); - DataConverterEntity.a.put("Slime", "minecraft:slime"); - DataConverterEntity.a.put("SmallFireball", "minecraft:small_fireball"); - DataConverterEntity.a.put("SnowMan", "minecraft:snowman"); - DataConverterEntity.a.put("Snowball", "minecraft:snowball"); - DataConverterEntity.a.put("SpectralArrow", "minecraft:spectral_arrow"); - DataConverterEntity.a.put("Spider", "minecraft:spider"); - DataConverterEntity.a.put("Squid", "minecraft:squid"); - DataConverterEntity.a.put("Stray", "minecraft:stray"); - DataConverterEntity.a.put("ThrownEgg", "minecraft:egg"); - DataConverterEntity.a.put("ThrownEnderpearl", "minecraft:ender_pearl"); - DataConverterEntity.a.put("ThrownExpBottle", "minecraft:xp_bottle"); - DataConverterEntity.a.put("ThrownPotion", "minecraft:potion"); - DataConverterEntity.a.put("Villager", "minecraft:villager"); - DataConverterEntity.a.put("VillagerGolem", "minecraft:villager_golem"); - DataConverterEntity.a.put("Witch", "minecraft:witch"); - DataConverterEntity.a.put("WitherBoss", "minecraft:wither"); - DataConverterEntity.a.put("WitherSkeleton", "minecraft:wither_skeleton"); - DataConverterEntity.a.put("WitherSkull", "minecraft:wither_skull"); - DataConverterEntity.a.put("Wolf", "minecraft:wolf"); - DataConverterEntity.a.put("XPOrb", "minecraft:xp_orb"); - DataConverterEntity.a.put("Zombie", "minecraft:zombie"); - DataConverterEntity.a.put("ZombieHorse", "minecraft:zombie_horse"); - DataConverterEntity.a.put("ZombieVillager", "minecraft:zombie_villager"); - } - - DataConverterEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterEntity.a.get(cmp.getString("id")); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - } - - private static class DataConverterPotionWater implements DataConverter { - - DataConverterPotionWater() { - } - - public int getDataVersion() { - return 806; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id"); - - if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals( - s)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (!nbttagcompound1.contains("Potion", 8)) { - nbttagcompound1.putString("Potion", "minecraft:water"); - } - - if (!cmp.contains("tag", 10)) { - cmp.put("tag", nbttagcompound1); - } - } - - return cmp; - } - - } - - private static class DataConverterShulker implements DataConverter { - - DataConverterShulker() { - } - - public int getDataVersion() { - return 808; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id")) && !cmp.contains("Color", 99)) { - cmp.putByte("Color", (byte) 10); - } - - return cmp; - } - - } - - private static class DataConverterShulkerBoxItem implements DataConverter { - - public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"}; - - DataConverterShulkerBoxItem() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker_box".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - - if (nbttagcompound2.getList("Items", 10).isEmpty()) { - nbttagcompound2.remove("Items"); - } - - int i = nbttagcompound2.getInt("Color"); - - nbttagcompound2.remove("Color"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - - cmp.putString("id", DataConverterShulkerBoxItem.a[i % 16]); - } - } - - return cmp; - } - - } - - private static class DataConverterShulkerBoxBlock implements DataConverter { - - DataConverterShulkerBoxBlock() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id"))) { - cmp.remove("Color"); - } - - return cmp; - } - - } - - private static class DataConverterLang implements DataConverter { - - DataConverterLang() { - } - - public int getDataVersion() { - return 816; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("lang", 8)) { - cmp.putString("lang", cmp.getString("lang").toLowerCase(Locale.ROOT)); - } - - return cmp; - } - - } - - private static class DataConverterTotem implements DataConverter { - - DataConverterTotem() { - } - - public int getDataVersion() { - return 820; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:totem".equals(cmp.getString("id"))) { - cmp.putString("id", "minecraft:totem_of_undying"); - } - - return cmp; - } - - } - - private static class DataConverterBedBlock implements DataConverter { - - private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); - - DataConverterBedBlock() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - try { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); - int i = nbttagcompound1.getInt("xPos"); - int j = nbttagcompound1.getInt("zPos"); - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("TileEntities", 10); - net.minecraft.nbt.ListTag nbttaglist1 = nbttagcompound1.getList("Sections", 10); - - for (int k = 0; k < nbttaglist1.size(); ++k) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); - byte b0 = nbttagcompound2.getByte("Y"); - byte[] abyte = nbttagcompound2.getByteArray("Blocks"); - - for (int l = 0; l < abyte.length; ++l) { - if (416 == (abyte[l] & 255) << 4) { - int i1 = l & 15; - int j1 = l >> 8 & 15; - int k1 = l >> 4 & 15; - net.minecraft.nbt.CompoundTag nbttagcompound3 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound3.putString("id", "bed"); - nbttagcompound3.putInt("x", i1 + (i << 4)); - nbttagcompound3.putInt("y", j1 + (b0 << 4)); - nbttagcompound3.putInt("z", k1 + (j << 4)); - nbttaglist.add(nbttagcompound3); - } - } - } - } catch (Exception exception) { - DataConverterBedBlock.a.warn("Unable to datafix Bed blocks, level format may be missing tags."); - } - - return cmp; - } - - } - - private static class DataConverterBedItem implements DataConverter { - - DataConverterBedItem() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:bed".equals(cmp.getString("id")) && cmp.getShort("Damage") == 0) { - cmp.putShort("Damage", (short) DyeColor.RED.getId()); - } - - return cmp; - } - - } - - private static class DataConverterSignText implements DataConverter { - - public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { - MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws - JsonParseException { - if (jsonelement.isJsonPrimitive()) { - return new TextComponent(jsonelement.getAsString()); - } else if (jsonelement.isJsonArray()) { - JsonArray jsonarray = jsonelement.getAsJsonArray(); - MutableComponent ichatbasecomponent = null; - - for (final JsonElement jsonelement1 : jsonarray) { - MutableComponent ichatbasecomponent1 = this.a( - jsonelement1, - jsonelement1.getClass(), - jsondeserializationcontext - ); - - if (ichatbasecomponent == null) { - ichatbasecomponent = ichatbasecomponent1; - } else { - ichatbasecomponent.append(ichatbasecomponent1); - } - } - - return ichatbasecomponent; - } else { - throw new JsonParseException("Don't know how to turn " + jsonelement + " into a Component"); - } - } - - public Object deserialize( - JsonElement jsonelement, - Type type, - JsonDeserializationContext jsondeserializationcontext - ) throws JsonParseException { - return this.a(jsonelement, type, jsondeserializationcontext); - } - }).create(); - - DataConverterSignText() { - } - - public int getDataVersion() { - return 101; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Sign".equals(cmp.getString("id"))) { - this.convert(cmp, "Text1"); - this.convert(cmp, "Text2"); - this.convert(cmp, "Text3"); - this.convert(cmp, "Text4"); - } - - return cmp; - } - - private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { - String s1 = nbttagcompound.getString(s); - Component object = null; - - if (!"null".equals(s1) && !StringUtil.isNullOrEmpty(s1)) { - if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) { - object = new TextComponent(s1); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); - if (object == null) { - object = new TextComponent(""); - } - } catch (JsonParseException ignored) { - } - - if (object == null) { - try { - object = Component.Serializer.fromJson(s1); - } catch (JsonParseException ignored) { - } - } - - if (object == null) { - try { - object = Component.Serializer.fromJsonLenient(s1); - } catch (JsonParseException ignored) { - } - } - - if (object == null) { - object = new TextComponent(s1); - } - } - } else { - object = new TextComponent(""); - } - - nbttagcompound.putString(s, Component.Serializer.toJson(object)); - } - - } - - private static class DataInspectorPlayerVehicle implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("RootVehicle", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); - - if (nbttagcompound1.contains("Entity", 10)) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - } - - return cmp; - } - - } - - private static class DataInspectorLevelPlayer implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Player", 10)) { - convertCompound(LegacyType.PLAYER, cmp, "Player", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorStructure implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.ListTag nbttaglist; - int j; - net.minecraft.nbt.CompoundTag nbttagcompound1; - - if (cmp.contains("entities", 9)) { - nbttaglist = cmp.getList("entities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.contains("nbt", 10)) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - } - - if (cmp.contains("blocks", 9)) { - nbttaglist = cmp.getList("blocks", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.contains("nbt", 10)) { - convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorChunks implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Level", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); - net.minecraft.nbt.ListTag nbttaglist; - int j; - - if (nbttagcompound1.contains("Entities", 9)) { - nbttaglist = nbttagcompound1.getList("Entities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert(LegacyType.ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); - } - } - - if (nbttagcompound1.contains("TileEntities", 9)) { - nbttaglist = nbttagcompound1.getList("TileEntities", 10); - - for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert(LegacyType.BLOCK_ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorEntityPassengers implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.contains("Passengers", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Passengers", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ENTITY, nbttaglist.getCompound(j), sourceVer, targetVer)); - } - } - - return cmp; - } - - } - - private static class DataInspectorPlayer implements DataInspector { - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - convertItems(cmp, "Inventory", sourceVer, targetVer); - convertItems(cmp, "EnderItems", sourceVer, targetVer); - if (cmp.contains("ShoulderEntityLeft", 10)) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityLeft", sourceVer, targetVer); - } - - if (cmp.contains("ShoulderEntityRight", 10)) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityRight", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorVillagers implements DataInspector { - - ResourceLocation entityVillager = getKey("EntityVillager"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (entityVillager.equals(new ResourceLocation(cmp.getString("id"))) && cmp.contains("Offers", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Offers"); - - if (nbttagcompound1.contains("Recipes", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); - - convertItem(nbttagcompound2, "buy", sourceVer, targetVer); - convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); - convertItem(nbttagcompound2, "sell", sourceVer, targetVer); - nbttaglist.set(j, nbttagcompound2); - } - } - } - - return cmp; - } - - } - - private static class DataInspectorMobSpawnerMinecart implements DataInspector { - - ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - String s = cmp.getString("id"); - if (entityMinecartMobSpawner.equals(new ResourceLocation(s))) { - cmp.putString("id", tileEntityMobSpawner.toString()); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", s); - } - - return cmp; - } - - } - - private static class DataInspectorMobSpawnerMobs implements DataInspector { - - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityMobSpawner.equals(new ResourceLocation(cmp.getString("id")))) { - if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); - - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - } - - convertCompound(LegacyType.ENTITY, cmp, "SpawnData", sourceVer, targetVer); - } - - return cmp; - } - - } - - private static class DataInspectorCommandBlock implements DataInspector { - - ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityCommand.equals(new ResourceLocation(cmp.getString("id")))) { - cmp.putString("id", "Control"); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", "MinecartCommandBlock"); - } - - return cmp; - } - - } - - @SuppressWarnings("unchecked") - private class WrappedDataFixer implements DataFixer { - - private final DataFixer realFixer; - - WrappedDataFixer(DataFixer realFixer) { - this.realFixer = realFixer; - } - - @Override - public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { - LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); - if (sourceVer < LEGACY_VERSION && legacyType != null) { - net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); - int desiredVersion = Math.min(targetVer, LEGACY_VERSION); - - cmp = convert(legacyType, cmp, sourceVer, desiredVersion); - sourceVer = desiredVersion; - dynamic = new Dynamic(OPS_NBT, cmp); - } - return realFixer.update(type, dynamic, sourceVer, targetVer); - } - - private net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int desiredVersion - ) { - List converters = PaperweightDataConverters.this.converters.get(type); - if (converters != null && !converters.isEmpty()) { - for (DataConverter converter : converters) { - int dataVersion = converter.getDataVersion(); - if (dataVersion > sourceVer && dataVersion <= desiredVersion) { - cmp = converter.convert(cmp); - } - } - } - - List inspectors = PaperweightDataConverters.this.inspectors.get(type); - if (inspectors != null && !inspectors.isEmpty()) { - for (DataInspector inspector : inspectors) { - cmp = inspector.inspect(cmp, sourceVer, desiredVersion); - } - } - - return cmp; - } - - @Override - public Schema getSchema(int i) { - return realFixer.getSchema(i); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java deleted file mode 100644 index e5ff26672..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; - -import com.mojang.authlib.GameProfile; -import net.minecraft.network.chat.ChatType; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stat; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.phys.Vec3; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -import java.util.OptionalInt; -import java.util.UUID; - -class PaperweightFakePlayer extends ServerPlayer { - - private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( - UUID.nameUUIDFromBytes("worldedit".getBytes()), - "[WorldEdit]" - ); - private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); - - PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); - } - - @Override - public Vec3 position() { - return ORIGIN; - } - - @Override - public void tick() { - } - - @Override - public void die(DamageSource damagesource) { - } - - @Override - public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) { - return this; - } - - @Override - public OptionalInt openMenu(MenuProvider factory) { - return OptionalInt.empty(); - } - - @Override - public void updateOptions(ServerboundClientInformationPacket packet) { - } - - @Override - public void displayClientMessage(Component message, boolean actionBar) { - } - - @Override - public void sendMessage(Component message, ChatType type, UUID sender) { - } - - @Override - public void awardStat(Stat stat, int amount) { - } - - @Override - public void awardStat(Stat stat) { - } - - @Override - public boolean isInvulnerableTo(DamageSource damageSource) { - return true; - } - - @Override - public void openTextEdit(SignBlockEntity sign) { - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java deleted file mode 100644 index e9656539a..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; - -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.world.block.BlockState; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.event.block.BlockPhysicsEvent; - -import java.lang.ref.WeakReference; -import java.util.Objects; -import javax.annotation.Nullable; - -public class PaperweightWorldNativeAccess implements - WorldNativeAccess { - - private static final int UPDATE = 1; - private static final int NOTIFY = 2; - - private final PaperweightAdapter adapter; - private final WeakReference world; - private SideEffectSet sideEffectSet; - - public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference world) { - this.adapter = adapter; - this.world = world; - } - - private ServerLevel getWorld() { - return Objects.requireNonNull(world.get(), "The reference to the world was lost"); - } - - @Override - public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { - this.sideEffectSet = sideEffectSet; - } - - @Override - public LevelChunk getChunk(int x, int z) { - return getWorld().getChunk(x, z); - } - - @Override - public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) { - int stateId = BlockStateIdAccess.getBlockStateId(state); - return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) { - return chunk.getBlockState(position); - } - - @Nullable - @Override - public net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState state - ) { - return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState block, - BlockPos position - ) { - return Block.updateFromNeighbourShapes(block, getWorld(), position); - } - - @Override - public BlockPos getPosition(int x, int y, int z) { - return new BlockPos(x, y, z); - } - - @Override - public void updateLightingForBlock(BlockPos position) { - getWorld().getChunkSource().getLightEngine().checkBlock(position); - } - - @Override - public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) { - return false; - } - - @Override - public void notifyBlockUpdate( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); - } - } - - @Override - public boolean isChunkTicking(LevelChunk chunk) { - return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - } - - @Override - public void markBlockChanged(LevelChunk chunk, BlockPos position) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().getChunkSource().blockChanged(position); - } - } - - @Override - public void notifyNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - ServerLevel world = getWorld(); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - world.updateNeighborsAt(pos, oldState.getBlock()); - } else { - // When we don't want events, manually run the physics without them. - Block block = oldState.getBlock(); - fireNeighborChanged(pos, world, block, pos.west()); - fireNeighborChanged(pos, world, block, pos.east()); - fireNeighborChanged(pos, world, block, pos.below()); - fireNeighborChanged(pos, world, block, pos.above()); - fireNeighborChanged(pos, world, block, pos.north()); - fireNeighborChanged(pos, world, block, pos.south()); - } - if (newState.hasAnalogOutputSignal()) { - world.updateNeighbourForOutputSignal(pos, newState.getBlock()); - } - } - - private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { - world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false); - } - - @Override - public void updateNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { - ServerLevel world = getWorld(); - // a == updateNeighbors - // b == updateDiagonalNeighbors - oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - CraftWorld craftWorld = world.getWorld(); - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), - CraftBlockData.fromData(newState) - ); - world.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } - newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit); - newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); - } - - @Override - public void onBlockStateChange( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - getWorld().onBlockStateChange(pos, oldState, newState); - } - - //FAWE start - @Override - public void flush() { - - } - //FAWE end - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java deleted file mode 100644 index e2481e72b..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java +++ /dev/null @@ -1,700 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; - -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter; -import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.entity.LazyBaseEntity; -import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; -import com.fastasyncworldedit.core.util.NbtUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.TileEntityBlock; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen.PaperweightRegen; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; -import com.sk89q.worldedit.world.RegenOptions; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.registry.BlockMaterial; -import io.papermc.lib.PaperLib; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.core.WritableRegistry; -import net.minecraft.nbt.IntTag; -import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.TreeType; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_18_R2.util.CraftNamespacedKey; -import org.bukkit.entity.Player; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.Set; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements - IDelegateBukkitImplAdapter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ - private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; - - public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); - } - - @Nullable - private static String getEntityId(Entity entity) { - ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); - return resourceLocation == null ? null : resourceLocation.toString(); - } - - private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { - entity.save(compoundTag); - } - - @Override - public BukkitImplAdapter getParent() { - return parent; - } - - private synchronized boolean init() { - if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) { - return false; - } - ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size - ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size - for (int i = 0; i < ibdToStateOrdinal.length; i++) { - BlockState blockState = BlockTypesCache.states[i]; - PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial(); - int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState()); - char ordinal = blockState.getOrdinalChar(); - ibdToStateOrdinal[id] = ordinal; - ordinalToIbdID[ordinal] = id; - } - Map>> properties = new HashMap<>(); - try { - for (Field field : BlockStateProperties.class.getDeclaredFields()) { - Object obj = field.get(null); - if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property state)) { - continue; - } - Property property; - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - property = new BooleanProperty( - state.getName(), - (List) ImmutableList.copyOf(state.getPossibleValues()) - ); - } else if (state instanceof DirectionProperty) { - property = new DirectionalProperty( - state.getName(), - state - .getPossibleValues() - .stream() - .map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase())) - .collect(Collectors.toList()) - ); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - property = new EnumProperty( - state.getName(), - state - .getPossibleValues() - .stream() - .map(e -> ((StringRepresentable) e).getSerializedName()) - .collect(Collectors.toList()) - ); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - property = new IntegerProperty( - state.getName(), - (List) ImmutableList.copyOf(state.getPossibleValues()) - ); - } else { - throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state - .getClass() - .getSimpleName()); - } - properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> { - if (v == null) { - v = new ArrayList<>(Collections.singletonList(property)); - } else { - v.add(property); - } - return v; - }); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } finally { - allBlockProperties = ImmutableMap.copyOf(properties); - } - initialised = true; - return true; - } - - @Override - public BlockMaterial getMaterial(BlockType blockType) { - Block block = getBlock(blockType); - return new PaperweightBlockMaterial(block); - } - - @Override - public synchronized BlockMaterial getMaterial(BlockState state) { - net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); - return new PaperweightBlockMaterial(blockState.getBlock(), blockState); - } - - public Block getBlock(BlockType blockType) { - return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); - } - - @Deprecated - @Override - public BlockState getBlock(Location location) { - Preconditions.checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - BlockState state = adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - return state; - } - - @Override - public BaseBlock getFullBlock(final Location location) { - Preconditions.checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - BlockState state = adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - if (state.getBlockType().getMaterial().hasContainer()) { - - // Read the NBT data - BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - } - } - - return state.toBaseBlock(); - } - - @Override - public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); - } - - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { - CraftChunk craftChunk = (CraftChunk) chunk; - LevelChunk levelChunk = craftChunk.getHandle(); - Level level = levelChunk.getLevel(); - - BlockPos blockPos = new BlockPos(x, y, z); - net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - LevelChunkSection[] levelChunkSections = levelChunk.getSections(); - int y4 = y >> 4; - LevelChunkSection section = levelChunkSections[y4]; - - net.minecraft.world.level.block.state.BlockState existing; - if (section == null) { - existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); - } else { - existing = section.getBlockState(x & 15, y & 15, z & 15); - } - - levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity - - CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null; - if (compoundTag != null || existing instanceof TileEntityBlock) { - level.setBlock(blockPos, blockState, 0); - // remove tile - if (compoundTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - BlockEntity blockEntity = level.getBlockEntity(blockPos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - blockEntity.load(tag); // readTagIntoTileEntity - load data - } - } - } else { - if (existing == blockState) { - return true; - } - levelChunk.setBlockState(blockPos, blockState, false); - } - if (update) { - level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0); - } - return true; - } - - @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); - } - - @Override - public BaseEntity getEntity(org.bukkit.entity.Entity entity) { - Preconditions.checkNotNull(entity); - - CraftEntity craftEntity = ((CraftEntity) entity); - Entity mcEntity = craftEntity.getHandle(); - - String id = getEntityId(mcEntity); - - if (id != null) { - EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { - final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); - //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); - }; - return new LazyBaseEntity(type, saveTag); - } else { - return null; - } - } - - @Override - public Component getRichBlockName(BlockType blockType) { - return parent.getRichBlockName(blockType); - } - - @Override - public Component getRichItemName(ItemType itemType) { - return parent.getRichItemName(itemType); - } - - @Override - public Component getRichItemName(BaseItemStack itemStack) { - return parent.getRichItemName(itemStack); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockState state) { - PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); - net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState(); - return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState)); - } - - @Override - public BlockState adapt(BlockData blockData) { - CraftBlockData cbd = ((CraftBlockData) blockData); - net.minecraft.world.level.block.state.BlockState ibd = cbd.getState(); - return adapt(ibd); - } - - public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { - return BlockTypesCache.states[adaptToChar(blockState)]; - } - - public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) { - int id = Block.BLOCK_STATE_REGISTRY.getId(blockState); - if (initialised) { - return ibdToStateOrdinal[id]; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - try { - init(); - return ibdToStateOrdinal[id]; - } catch (ArrayIndexOutOfBoundsException e1) { - LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!", - blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1 - ); - return BlockTypesCache.ReservedIDs.AIR; - } - } - } - - public char ibdIDToOrdinal(int id) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal[id]; - } - init(); - return ibdToStateOrdinal[id]; - } - } - - @Override - public char[] getIbdToStateOrdinal() { - if (initialised) { - return ibdToStateOrdinal; - } - synchronized (this) { - if (initialised) { - return ibdToStateOrdinal; - } - init(); - return ibdToStateOrdinal; - } - } - - public int ordinalToIbdID(char ordinal) { - if (initialised) { - return ordinalToIbdID[ordinal]; - } - synchronized (this) { - if (initialised) { - return ordinalToIbdID[ordinal]; - } - init(); - return ordinalToIbdID[ordinal]; - } - } - - @Override - public int[] getOrdinalToIbdID() { - if (initialised) { - return ordinalToIbdID; - } - synchronized (this) { - if (initialised) { - return ordinalToIbdID; - } - init(); - return ordinalToIbdID; - } - } - - @Override - public > BlockData adapt(B state) { - PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); - return material.getCraftBlockData(); - } - - @Override - public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); - ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); - if (map != null && map.wasAccessibleSinceLastSave()) { - // PlayerChunk.d players = map.players; - Stream stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) - */ Stream.empty(); - - ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle(); - stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer) - .forEach(entityPlayer -> { - synchronized (chunkPacket) { - ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket(); - if (nmsPacket == null) { - nmsPacket = mapUtil.create(this, chunkPacket); - chunkPacket.setNativePacket(nmsPacket); - } - try { - FaweCache.INSTANCE.CHUNK_FLAG.get().set(true); - entityPlayer.connection.send(nmsPacket); - } finally { - FaweCache.INSTANCE.CHUNK_FLAG.get().set(false); - } - } - }); - } - } - - @Override - public Map> getProperties(BlockType blockType) { - return getParent().getProperties(blockType); - } - - @Override - public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) { - int internalId = BlockStateIdAccess.getBlockStateId(blockState); - net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); - return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) - ); - } - - @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { - ItemStack stack = new ItemStack( - Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), - baseItemStack.getAmount() - ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); - return CraftItemStack.asCraftMirror(stack); - } - - @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; - } - - @Override - public List getEntities(org.bukkit.World world) { - // Quickly add each entity to a list copy. - List mcEntities = new ArrayList<>(); - ((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add); - - List list = new ArrayList<>(); - mcEntities.forEach((mcEnt) -> { - org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); - if (bukkitEntity.isValid()) { - list.add(bukkitEntity); - } - - }); - return list; - } - - @Override - public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { - final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; - } - - @Override - public Tag toNative(net.minecraft.nbt.Tag foreign) { - return parent.toNative(foreign); - } - - @Override - public BinaryTag toNativeBinary(final net.minecraft.nbt.Tag foreign) { - return parent.toNativeBinary(foreign); - } - - @Override - public net.minecraft.nbt.Tag fromNative(Tag foreign) { - if (foreign instanceof PaperweightLazyCompoundTag) { - return ((PaperweightLazyCompoundTag) foreign).get(); - } - return (net.minecraft.nbt.Tag) parent.fromNative(foreign); - } - - @Override - public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception { - return new PaperweightRegen(bukkitWorld, region, target, options).regenerate(); - } - - @Override - public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) { - return new PaperweightGetBlocks(world, chunkX, chunkZ); - } - - @Override - public int getInternalBiomeId(BiomeType biomeType) { - final Registry registry = MinecraftServer - .getServer() - .registryAccess() - .ownedRegistryOrThrow(Registry.BIOME_REGISTRY); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); - Biome biome = registry.get(resourceLocation); - return registry.getId(biome); - } - - @Override - public Iterable getRegisteredBiomes() { - WritableRegistry biomeRegistry = (WritableRegistry) ((CraftServer) Bukkit.getServer()) - .getServer() - .registryAccess() - .ownedRegistryOrThrow( - Registry.BIOME_REGISTRY); - List keys = biomeRegistry.stream() - .map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); - List namespacedKeys = new ArrayList<>(); - for (ResourceLocation key : keys) { - try { - namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key)); - } catch (IllegalArgumentException e) { - LOGGER.error("Error converting biome key {}", key.toString(), e); - } - } - return namespacedKeys; - } - - @Override - public RelighterFactory getRelighterFactory() { - if (PaperLib.isPaper()) { - return new PaperweightStarlightRelighterFactory(); - } else { - return new NMSRelighterFactory(); - } - } - - @Override - public Map>> getAllProperties() { - if (initialised) { - return allBlockProperties; - } - synchronized (this) { - if (initialised) { - return allBlockProperties; - } - init(); - return allBlockProperties; - } - } - - @Override - public IBatchProcessor getTickingPostProcessor() { - return new PaperweightPostProcessor(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java deleted file mode 100644 index ef7fc98ac..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java +++ /dev/null @@ -1,286 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; - -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.math.IntPair; -import com.fastasyncworldedit.core.util.TaskManager; -import com.fastasyncworldedit.core.util.task.RunnableVal; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.world.block.BlockState; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.event.block.BlockPhysicsEvent; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess { - - private static final int UPDATE = 1; - private static final int NOTIFY = 2; - private static final Direction[] NEIGHBOUR_ORDER = { - Direction.EAST, - Direction.WEST, - Direction.DOWN, - Direction.UP, - Direction.NORTH, - Direction.SOUTH - }; - private final PaperweightFaweAdapter paperweightFaweAdapter; - private final WeakReference level; - private final AtomicInteger lastTick; - private final Set cachedChanges = new HashSet<>(); - private final Set cachedChunksToSend = new HashSet<>(); - private SideEffectSet sideEffectSet; - - public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { - this.paperweightFaweAdapter = paperweightFaweAdapter; - this.level = level; - // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. - // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - this.lastTick = new AtomicInteger(MinecraftServer.currentTick); - } - - private Level getLevel() { - return Objects.requireNonNull(level.get(), "The reference to the world was lost"); - } - - @Override - public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { - this.sideEffectSet = sideEffectSet; - } - - @Override - public LevelChunk getChunk(int x, int z) { - return getLevel().getChunk(x, z); - } - - @Override - public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) { - int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar()); - return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState(); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) { - return levelChunk.getBlockState(blockPos); - } - - @Nullable - @Override - public synchronized net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk levelChunk, BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState blockState - ) { - int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { - return levelChunk.setBlockState(blockPos, blockState, - this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) - ); - } - // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) - cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ())); - boolean nextTick = lastTick.get() > currentTick; - if (nextTick || cachedChanges.size() >= 1024) { - if (nextTick) { - lastTick.set(currentTick); - } - flushAsync(nextTick); - } - return blockState; - } - - @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState blockState, - BlockPos blockPos - ) { - return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos); - } - - @Override - public BlockPos getPosition(int x, int y, int z) { - return new BlockPos(x, y, z); - } - - @Override - public void updateLightingForBlock(BlockPos blockPos) { - getLevel().getChunkSource().getLightEngine().checkBlock(blockPos); - } - - @Override - public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) { - // We will assume that the tile entity was created for us, - // though we do not do this on the other versions - BlockEntity blockEntity = getLevel().getBlockEntity(blockPos); - if (blockEntity == null) { - return false; - } - net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag); - blockEntity.load((CompoundTag) nativeTag); - return true; - } - - @Override - public void notifyBlockUpdate( - LevelChunk levelChunk, BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { - getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY); - } - } - - @Override - public boolean isChunkTicking(LevelChunk levelChunk) { - return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - } - - @Override - public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) { - if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { - ((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos); - } - } - - @Override - public void notifyNeighbors( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - Level level = getLevel(); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - level.blockUpdated(blockPos, oldState.getBlock()); - } else { - // When we don't want events, manually run the physics without them. - // Un-nest neighbour updating - for (Direction direction : NEIGHBOUR_ORDER) { - BlockPos shifted = blockPos.relative(direction); - level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false); - } - } - if (newState.hasAnalogOutputSignal()) { - level.updateNeighbourForOutputSignal(blockPos, newState.getBlock()); - } - } - - @Override - public void updateNeighbors( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { - Level level = getLevel(); - // a == updateNeighbors - // b == updateDiagonalNeighbors - oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - CraftWorld craftWorld = level.getWorld(); - if (craftWorld != null) { - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), - CraftBlockData.fromData(newState) - ); - level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } - } - newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit); - newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); - } - - @Override - public void onBlockStateChange( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - getLevel().onBlockStateChange(blockPos, oldState, newState); - } - - private synchronized void flushAsync(final boolean sendChunks) { - final Set changes = Set.copyOf(cachedChanges); - cachedChanges.clear(); - final Set toSend; - if (sendChunks) { - toSend = Set.copyOf(cachedChunksToSend); - cachedChunksToSend.clear(); - } else { - toSend = Collections.emptySet(); - } - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - if (!sendChunks) { - return; - } - for (IntPair chunk : toSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); - } - - @Override - public synchronized void flush() { - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - for (IntPair chunk : cachedChunksToSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - if (Fawe.isMainThread()) { - runnableVal.run(); - } else { - TaskManager.taskManager().sync(runnableVal); - } - cachedChanges.clear(); - cachedChunksToSend.clear(); - } - - private record CachedChange( - LevelChunk levelChunk, - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState blockState - ) { - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java deleted file mode 100644 index 91a5abede..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java +++ /dev/null @@ -1,1157 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; - -import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks; -import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.fastasyncworldedit.core.math.BitArrayUnstretched; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.google.common.collect.Iterables; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import io.papermc.lib.PaperLib; -import io.papermc.paper.event.block.BeaconDeactivatedEvent; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.IdMap; -import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; -import net.minecraft.nbt.IntTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.util.BitStorage; -import net.minecraft.util.ZeroBitStorage; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.entity.BeaconBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.DataLayer; -import net.minecraft.world.level.chunk.HashMapPalette; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.LinearPalette; -import net.minecraft.world.level.chunk.Palette; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.lighting.LevelLightEngine; -import org.apache.logging.log4j.Logger; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock; -import org.bukkit.event.entity.CreatureSpawnEvent; - -import javax.annotation.Nonnull; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.Semaphore; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); - private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin - .getInstance() - .getBukkitImplAdapter()); - private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); - private final ServerLevel serverLevel; - private final int chunkX; - private final int chunkZ; - private final int minHeight; - private final int maxHeight; - private final int minSectionPosition; - private final int maxSectionPosition; - private final Registry biomeRegistry; - private final IdMap> biomeHolderIdMap; - private LevelChunkSection[] sections; - private LevelChunk levelChunk; - private DataLayer[] blockLight; - private DataLayer[] skyLight; - private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; - private boolean forceLoadSections = true; - private boolean lightUpdate = false; - - public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { - this(((CraftWorld) world).getHandle(), chunkX, chunkZ); - } - - public PaperweightGetBlocks(ServerLevel serverLevel, int chunkX, int chunkZ) { - super(serverLevel.getMinBuildHeight() >> 4, (serverLevel.getMaxBuildHeight() - 1) >> 4); - this.serverLevel = serverLevel; - this.chunkX = chunkX; - this.chunkZ = chunkZ; - this.minHeight = serverLevel.getMinBuildHeight(); - this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.minSectionPosition = minHeight >> 4; - this.maxSectionPosition = maxHeight >> 4; - this.skyLight = new DataLayer[getSectionCount()]; - this.blockLight = new DataLayer[getSectionCount()]; - this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); - this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); - } - - public int getChunkX() { - return chunkX; - } - - public int getChunkZ() { - return chunkZ; - } - - @Override - public boolean isCreateCopy() { - return createCopy; - } - - @Override - public void setCreateCopy(boolean createCopy) { - this.createCopy = createCopy; - } - - @Override - public IChunkGet getCopy() { - return copy; - } - - @Override - public void setLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { - if (light != null) { - lightUpdate = true; - try { - fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void setSkyLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { - if (light != null) { - lightUpdate = true; - try { - fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void setHeightmapToGet(HeightMapType type, int[] data) { - // height + 1 to match server internal - BitArrayUnstretched bitArray = new BitArrayUnstretched(MathMan.log2nlz(getChunk().getHeight() + 1), 256); - bitArray.fromRaw(data); - Heightmap.Types nativeType = Heightmap.Types.valueOf(type.name()); - Heightmap heightMap = getChunk().heightmaps.get(nativeType); - heightMap.setRawData(getChunk(), nativeType, bitArray.getData()); - } - - @Override - public int getMaxY() { - return maxHeight; - } - - @Override - public int getMinY() { - return minHeight; - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - LevelChunkSection section = getSections(false)[(y >> 4) - getMinSectionPosition()]; - Holder biomes = section.getNoiseBiome(x >> 2, (y & 15) >> 2, z >> 2); - return PaperweightPlatformAdapter.adapt(biomes, serverLevel); - } - - @Override - public void removeSectionLighting(int layer, boolean sky) { - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.BLOCK).getDataLayerData( - sectionPos); - if (dataLayer != null) { - lightUpdate = true; - synchronized (dataLayer) { - byte[] bytes = dataLayer.getData(); - Arrays.fill(bytes, (byte) 0); - } - } - if (sky) { - SectionPos sectionPos1 = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer1 = serverLevel - .getChunkSource() - .getLightEngine() - .getLayerListener(LightLayer.SKY) - .getDataLayerData(sectionPos1); - if (dataLayer1 != null) { - lightUpdate = true; - synchronized (dataLayer1) { - byte[] bytes = dataLayer1.getData(); - Arrays.fill(bytes, (byte) 0); - } - } - } - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( - chunkX << 4), y, (z & 15) + ( - chunkZ << 4))); - if (blockEntity == null) { - return null; - } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); - } - - @Override - public Map getTiles() { - Map nmsTiles = getChunk().getBlockEntities(); - if (nmsTiles.isEmpty()) { - return Collections.emptyMap(); - } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); - } - - @Override - public int getSkyLight(int x, int y, int z) { - int layer = y >> 4; - int alayer = layer - getMinSectionPosition(); - if (skyLight[alayer] == null) { - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = - serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.SKY).getDataLayerData(sectionPos); - // If the server hasn't generated the section's NibbleArray yet, it will be null - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. - Arrays.fill(LAYER_COUNT, (byte) 15); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( - LightLayer.BLOCK, - sectionPos, - dataLayer, - true - ); - } - skyLight[alayer] = dataLayer; - } - return skyLight[alayer].get(x & 15, y & 15, z & 15); - } - - @Override - public int getEmittedLight(int x, int y, int z) { - int layer = y >> 4; - int alayer = layer - getMinSectionPosition(); - if (blockLight[alayer] == null) { - serverLevel.getRawBrightness(new BlockPos(1, 1, 1), 5); - SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); - DataLayer dataLayer = serverLevel - .getChunkSource() - .getLightEngine() - .getLayerListener(LightLayer.BLOCK) - .getDataLayerData(sectionPos); - // If the server hasn't generated the section's DataLayer yet, it will be null - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. - Arrays.fill(LAYER_COUNT, (byte) 15); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true - ); - } - blockLight[alayer] = dataLayer; - } - return blockLight[alayer].get(x & 15, y & 15, z & 15); - } - - @Override - public int[] getHeightMap(HeightMapType type) { - long[] longArray = getChunk().heightmaps.get(Heightmap.Types.valueOf(type.name())).getRawData(); - BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256, longArray); - return bitArray.toRaw(new int[256]); - } - - @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); - if (entity != null) { - org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); - } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { - return tag; - } - } - return null; - } - - @Override - public Set getEntities() { - List entities = PaperweightPlatformAdapter.getEntities(getChunk()); - if (entities.isEmpty()) { - return Collections.emptySet(); - } - int size = entities.size(); - return new AbstractSet<>() { - @Override - public int size() { - return size; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { - return false; - } - UUID getUUID = getTag.getUUID(); - for (Entity entity : entities) { - UUID uuid = entity.getUUID(); - if (uuid.equals(getUUID)) { - return true; - } - } - return false; - } - - @Nonnull - @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); - return result.iterator(); - } - }; - } - - private void removeEntity(Entity entity) { - entity.discard(); - } - - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) { - return PaperweightPlatformAdapter.ensureLoaded(nmsWorld, chunkX, chunkZ); - } - - @Override - @SuppressWarnings("rawtypes") - public synchronized > T call(IChunkSet set, Runnable finalizer) { - forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; - try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - - // Remove existing tiles. Create a copy so that we can remove blocks - Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); - List beacons = null; - if (!chunkTiles.isEmpty()) { - for (Map.Entry entry : chunkTiles.entrySet()) { - final BlockPos pos = entry.getKey(); - final int lx = pos.getX() & 15; - final int ly = pos.getY(); - final int lz = pos.getZ() & 15; - final int layer = ly >> 4; - if (!set.hasSection(layer)) { - continue; - } - - int ordinal = set.getBlock(lx, ly, lz).getOrdinal(); - if (ordinal != BlockTypesCache.ReservedIDs.__RESERVED__) { - BlockEntity tile = entry.getValue(); - if (PaperLib.isPaper() && tile instanceof BeaconBlockEntity) { - if (beacons == null) { - beacons = new ArrayList<>(); - } - beacons.add(tile); - PaperweightPlatformAdapter.removeBeacon(tile, nmsChunk); - continue; - } - nmsChunk.removeBlockEntity(tile.getBlockPos()); - if (createCopy) { - copy.storeTile(tile); - } - } - } - } - final BiomeType[][] biomes = set.getBiomes(); - - int bitMask = 0; - synchronized (nmsChunk) { - LevelChunkSection[] levelChunkSections = nmsChunk.getSections(); - - for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) { - - int getSectionIndex = layerNo - getMinSectionPosition(); - int setSectionIndex = layerNo - set.getMinSectionPosition(); - - if (!set.hasSection(layerNo)) { - // No blocks, but might be biomes present. Handle this lazily. - if (biomes == null) { - continue; - } - if (layerNo < set.getMinSectionPosition() || layerNo > set.getMaxSectionPosition()) { - continue; - } - if (biomes[setSectionIndex] != null) { - synchronized (super.sectionLocks[getSectionIndex]) { - LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; - if (createCopy && existingSection != null) { - copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); - } - - if (existingSection == null) { - PalettedContainer> biomeData = PaperweightPlatformAdapter.getBiomePalettedContainer( - biomes[setSectionIndex], - biomeHolderIdMap - ); - LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( - layerNo, - new char[4096], - adapter, - biomeRegistry, - biomeData - ); - if (PaperweightPlatformAdapter.setSectionAtomic( - levelChunkSections, - null, - newSection, - getSectionIndex - )) { - updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); - continue; - } else { - existingSection = levelChunkSections[getSectionIndex]; - if (existingSection == null) { - LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, - getSectionIndex - ); - continue; - } - } - } else { - PalettedContainer> biomeData = existingSection.getBiomes(); - setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData); - } - } - } - continue; - } - - bitMask |= 1 << getSectionIndex; - - // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to - // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); - - // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was - // submitted to keep loaded internal chunks to queue target size. - synchronized (super.sectionLocks[getSectionIndex]) { - - LevelChunkSection newSection; - LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; - // Don't attempt to tick section whilst we're editing - if (existingSection != null) { - PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } - } - - if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(getSectionIndex, copyArr); - if (biomes != null && existingSection != null) { - copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); - } - } - - if (existingSection == null) { - PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( - biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null - ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); - newSection = PaperweightPlatformAdapter.newChunkSection( - layerNo, - setArr, - adapter, - biomeRegistry, - biomeData - ); - if (PaperweightPlatformAdapter.setSectionAtomic( - levelChunkSections, - null, - newSection, - getSectionIndex - )) { - updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex); - continue; - } else { - existingSection = levelChunkSections[getSectionIndex]; - if (existingSection == null) { - LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, - getSectionIndex - ); - continue; - } - } - } - - //ensure that the server doesn't try to tick the chunksection while we're editing it. (Again) - PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } - DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection); - - // Synchronize to prevent further acquisitions - synchronized (lock) { - lock.acquire(); // Wait until we have the lock - lock.release(); - try { - sectionLock.writeLock().lock(); - if (this.getChunk() != nmsChunk) { - this.levelChunk = nmsChunk; - this.sections = null; - this.reset(); - } else if (existingSection != getSections(false)[getSectionIndex]) { - this.sections[getSectionIndex] = existingSection; - this.reset(); - } else if (!Arrays.equals( - update(getSectionIndex, new char[4096], true), - loadPrivately(layerNo) - )) { - this.reset(layerNo); - /*} else if (lock.isModified()) { - this.reset(layerNo);*/ - } - } finally { - sectionLock.writeLock().unlock(); - } - - PalettedContainer> biomeData = existingSection.getBiomes(); - - if (biomes != null && biomes[setSectionIndex] != null) { - setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData); - } - - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - adapter, - biomeRegistry, - biomeData - ); - if (!PaperweightPlatformAdapter.setSectionAtomic( - levelChunkSections, - existingSection, - newSection, - getSectionIndex - )) { - LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, - getSectionIndex - ); - } else { - updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex); - } - } - } - } - - Map heightMaps = set.getHeightMaps(); - for (Map.Entry entry : heightMaps.entrySet()) { - PaperweightGetBlocks.this.setHeightmapToGet(entry.getKey(), entry.getValue()); - } - PaperweightGetBlocks.this.setLightingToGet( - set.getLight(), - set.getMinSectionPosition(), - set.getMaxSectionPosition() - ); - PaperweightGetBlocks.this.setSkyLightingToGet( - set.getSkyLight(), - set.getMinSectionPosition(), - set.getMaxSectionPosition() - ); - - Runnable[] syncTasks = null; - - int bx = chunkX << 4; - int bz = chunkZ << 4; - - // Call beacon deactivate events here synchronously - // list will be null on spigot, so this is an implicit isPaper check - if (beacons != null && !beacons.isEmpty()) { - final List finalBeacons = beacons; - - syncTasks = new Runnable[4]; - - syncTasks[3] = () -> { - for (BlockEntity beacon : finalBeacons) { - BeaconBlockEntity.playSound(beacon.getLevel(), beacon.getBlockPos(), SoundEvents.BEACON_DEACTIVATE); - new BeaconDeactivatedEvent(CraftBlock.at(beacon.getLevel(), beacon.getBlockPos())).callEvent(); - } - }; - } - - Set entityRemoves = set.getEntityRemoves(); - if (entityRemoves != null && !entityRemoves.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[3]; - } - - syncTasks[2] = () -> { - Set entitiesRemoved = new HashSet<>(); - final List entities = PaperweightPlatformAdapter.getEntities(nmsChunk); - - for (Entity entity : entities) { - UUID uuid = entity.getUUID(); - if (entityRemoves.contains(uuid)) { - if (createCopy) { - copy.storeEntity(entity); - } - removeEntity(entity); - entitiesRemoved.add(uuid); - entityRemoves.remove(uuid); - } - } - if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { - for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); - if (entity != null) { - removeEntity(entity); - } - } - } - // Only save entities that were actually removed to history - set.getEntityRemoves().clear(); - set.getEntityRemoves().addAll(entitiesRemoved); - }; - } - - Set entities = set.getEntities(); - if (entities != null && !entities.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[2]; - } - - syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); - while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); - if (idTag == null || posTag == null || rotTag == null) { - LOGGER.error("Unknown entity tag: {}", nativeTag); - continue; - } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); - - EntityType type = EntityType.byString(id).orElse(null); - if (type != null) { - Entity entity = type.create(nmsWorld); - if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); - for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.load(tag); - entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { - LOGGER.warn( - "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", - id, - nmsWorld.getWorld().getName(), - x, - y, - z - ); - // Unsuccessful create should not be saved to history - iterator.remove(); - } - } - } - } - }; - } - - // set tiles - Map tiles = set.getTiles(); - if (tiles != null && !tiles.isEmpty()) { - if (syncTasks == null) { - syncTasks = new Runnable[1]; - } - - syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); - final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; - final BlockPos pos = new BlockPos(x, y, z); - - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); - if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); - } - if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - tileEntity.load(tag); - } - } - } - }; - } - - Runnable callback; - if (bitMask == 0 && biomes == null && !lightUpdate) { - callback = null; - } else { - int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; - callback = () -> { - // Set Modified - nmsChunk.setLightCorrect(true); // Set Modified - nmsChunk.mustNotSave = false; - nmsChunk.setUnsaved(true); - // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); - } - if (finalizer != null) { - finalizer.run(); - } - }; - } - if (syncTasks != null) { - QueueHandler queueHandler = Fawe.instance().getQueueHandler(); - Runnable[] finalSyncTasks = syncTasks; - - // Chain the sync tasks and the callback - Callable chain = () -> { - try { - // Run the sync tasks - for (Runnable task : finalSyncTasks) { - if (task != null) { - task.run(); - } - } - if (callback == null) { - if (finalizer != null) { - finalizer.run(); - } - return null; - } else { - return queueHandler.async(callback, null); - } - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - }; - //noinspection unchecked - required at compile time - return (T) (Future) queueHandler.sync(chain); - } else { - if (callback == null) { - if (finalizer != null) { - finalizer.run(); - } - } else { - callback.run(); - } - } - } - return null; - } catch (Throwable e) { - e.printStackTrace(); - return null; - } finally { - forceLoadSections = true; - } - } - - private void updateGet( - LevelChunk nmsChunk, - LevelChunkSection[] chunkSections, - LevelChunkSection section, - char[] arr, - int layer - ) { - try { - sectionLock.writeLock().lock(); - if (this.getChunk() != nmsChunk) { - this.levelChunk = nmsChunk; - this.sections = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); - this.reset(); - } - if (this.sections == null) { - this.sections = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); - } - if (this.sections[layer] != section) { - // Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords - this.sections[layer] = new LevelChunkSection[]{section}.clone()[0]; - } - } finally { - sectionLock.writeLock().unlock(); - } - this.blocks[layer] = arr; - } - - private char[] loadPrivately(int layer) { - layer -= getMinSectionPosition(); - if (super.sections[layer] != null) { - synchronized (super.sectionLocks[layer]) { - if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; - } - } - } - return PaperweightGetBlocks.this.update(layer, null, true); - } - - @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); - } - - /** - * Update a given (nullable) data array to the current data stored in the server's chunk, associated with this - * {@link PaperweightPlatformAdapter} instance. Not synchronised to the {@link PaperweightPlatformAdapter} instance as synchronisation - * is handled where necessary in the method, and should otherwise be handled correctly by this method's caller. - * - * @param layer layer index (0 may denote a negative layer in the world, e.g. at y=-32) - * @param data array to be updated/filled with data or null - * @param aggressive if the cached section array should be re-acquired. - * @return the given array to be filled with data, or a new array if null is given. - */ - @Override - @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { - LevelChunkSection section = getSections(aggressive)[layer]; - // Section is null, return empty array - if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; - } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - Semaphore lock = PaperweightPlatformAdapter.applyLock(section); - synchronized (lock) { - // Efficiently convert ChunkSection to raw data - try { - lock.acquire(); - - final PalettedContainer blocks = section.getStates(); - final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocks); - final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); - - if (bits instanceof ZeroBitStorage) { - Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper - return data; - } - - final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get(dataObject); - - final int bitsPerEntry = bits.getBits(); - final long[] blockStates = bits.getRaw(); - - new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data); - - int num_palette; - if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { - num_palette = palette.getSize(); - } else { - // The section's palette is the global block palette. - for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; - char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; - } - return data; - } - - char[] paletteToOrdinal = FaweCache.INSTANCE.PALETTE_TO_BLOCK_CHAR.get(); - try { - if (num_palette != 1) { - for (int i = 0; i < num_palette; i++) { - char ordinal = ordinal(palette.valueFor(i), adapter); - paletteToOrdinal[i] = ordinal; - } - for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; - char val = paletteToOrdinal[paletteVal]; - if (val == Character.MAX_VALUE) { - val = ordinal(palette.valueFor(i), adapter); - paletteToOrdinal[i] = val; - } - data[i] = val; - } - } else { - char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); - } - } finally { - for (int i = 0; i < num_palette; i++) { - paletteToOrdinal[i] = Character.MAX_VALUE; - } - } - return data; - } catch (IllegalAccessException | InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } finally { - lock.release(); - } - } - } - - private char ordinal(BlockState ibd, PaperweightFaweAdapter adapter) { - if (ibd == null) { - return BlockTypesCache.ReservedIDs.AIR; - } else { - return adapter.adaptToChar(ibd); - } - } - - public LevelChunkSection[] getSections(boolean force) { - force &= forceLoadSections; - sectionLock.readLock().lock(); - LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); - if (tmp == null || force) { - try { - sectionLock.writeLock().lock(); - tmp = sections; - if (tmp == null || force) { - LevelChunkSection[] chunkSections = getChunk().getSections(); - tmp = new LevelChunkSection[chunkSections.length]; - System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length); - sections = tmp; - } - } finally { - sectionLock.writeLock().unlock(); - } - } - return tmp; - } - - public LevelChunk getChunk() { - LevelChunk levelChunk = this.levelChunk; - if (levelChunk == null) { - synchronized (this) { - levelChunk = this.levelChunk; - if (levelChunk == null) { - this.levelChunk = levelChunk = ensureLoaded(this.serverLevel, chunkX, chunkZ); - } - } - } - return levelChunk; - } - - private void fillLightNibble(char[][] light, LightLayer lightLayer, int minSectionPosition, int maxSectionPosition) { - for (int Y = 0; Y <= maxSectionPosition - minSectionPosition; Y++) { - if (light[Y] == null) { - continue; - } - SectionPos sectionPos = SectionPos.of(levelChunk.getPos(), Y + minSectionPosition); - DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(lightLayer).getDataLayerData( - sectionPos); - if (dataLayer == null) { - byte[] LAYER_COUNT = new byte[2048]; - Arrays.fill(LAYER_COUNT, lightLayer == LightLayer.SKY ? (byte) 15 : (byte) 0); - dataLayer = new DataLayer(LAYER_COUNT); - ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( - lightLayer, - sectionPos, - dataLayer, - true - ); - } - synchronized (dataLayer) { - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - int i = y << 8 | z << 4 | x; - if (light[Y][i] < 16) { - dataLayer.set(x, y, z, light[Y][i]); - } - } - } - } - } - } - } - - private void setBiomesToPalettedContainer( - final BiomeType[] biomes, - PalettedContainer> data - ) { - int index = 0; - if (biomes == null) { - return; - } - for (int y = 0; y < 4; y++) { - for (int z = 0; z < 4; z++) { - for (int x = 0; x < 4; x++, index++) { - BiomeType biomeType = biomes[index]; - if (biomeType == null) { - continue; - } - data.set( - x, - y, - z, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)) - ); - } - } - } - } - - @Override - public boolean hasSection(int layer) { - layer -= getMinSectionPosition(); - return getSections(false)[layer] != null; - } - - @Override - @SuppressWarnings("unchecked") - public synchronized boolean trim(boolean aggressive) { - skyLight = new DataLayer[getSectionCount()]; - blockLight = new DataLayer[getSectionCount()]; - if (aggressive) { - sectionLock.writeLock().lock(); - sections = null; - levelChunk = null; - sectionLock.writeLock().unlock(); - return super.trim(true); - } else if (sections == null) { - // don't bother trimming if there are no sections stored. - return true; - } else { - for (int i = getMinSectionPosition(); i <= getMaxSectionPosition(); i++) { - int layer = i - getMinSectionPosition(); - if (!hasSection(i) || !super.sections[layer].isFull()) { - continue; - } - LevelChunkSection existing = getSections(true)[layer]; - try { - final PalettedContainer blocksExisting = existing.getStates(); - - final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocksExisting); - final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get( - dataObject); - int paletteSize; - - if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { - paletteSize = palette.getSize(); - } else { - super.trim(false, i); - continue; - } - if (paletteSize == 1) { - //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. - continue; - } - super.trim(false, i); - } catch (IllegalAccessException ignored) { - super.trim(false, i); - } - } - return true; - } - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java deleted file mode 100644 index 991c3d1f9..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java +++ /dev/null @@ -1,236 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; - -import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.fastasyncworldedit.core.queue.IBlocks; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import net.minecraft.core.Holder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.PalettedContainer; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Future; - -public class PaperweightGetBlocks_Copy implements IChunkGet { - - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); - private final char[][] blocks; - private final int minHeight; - private final int maxHeight; - final ServerLevel serverLevel; - final LevelChunk levelChunk; - private PalettedContainer>[] biomes = null; - - protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { - this.levelChunk = levelChunk; - this.serverLevel = levelChunk.level; - this.minHeight = serverLevel.getMinBuildHeight(); - this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; - } - - protected void storeTile(BlockEntity blockEntity) { - tiles.put( - BlockVector3.at( - blockEntity.getBlockPos().getX(), - blockEntity.getBlockPos().getY(), - blockEntity.getBlockPos().getZ() - ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) - ); - } - - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); - } - - @Override - public Set getEntities() { - return this.entities; - } - - @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { - return tag; - } - } - return null; - } - - @Override - public boolean isCreateCopy() { - return false; - } - - @Override - public void setCreateCopy(boolean createCopy) { - } - - @Override - public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - } - - @Override - public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - } - - @Override - public void setHeightmapToGet(HeightMapType type, int[] data) { - } - - @Override - public int getMaxY() { - return maxHeight; - } - - @Override - public int getMinY() { - return minHeight; - } - - @Override - public int getMaxSectionPosition() { - return maxHeight >> 4; - } - - @Override - public int getMinSectionPosition() { - return minHeight >> 4; - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - Holder biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2); - return PaperweightPlatformAdapter.adapt(biome, serverLevel); - } - - @Override - public void removeSectionLighting(int layer, boolean sky) { - } - - @Override - public boolean trim(boolean aggressive, int layer) { - return false; - } - - @Override - public IBlocks reset() { - return null; - } - - @Override - public int getSectionCount() { - return serverLevel.getSectionsCount(); - } - - protected void storeSection(int layer, char[] data) { - blocks[layer] = data; - } - - protected void storeBiomes(int layer, PalettedContainer> biomeData) { - if (biomes == null) { - biomes = new PalettedContainer[getSectionCount()]; - } - biomes[layer] = biomeData; - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); - } - - @Override - public boolean hasSection(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer] != null; - } - - @Override - public char[] load(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer]; - } - - @Override - public char[] loadIfPresent(int layer) { - layer -= getMinSectionPosition(); - return blocks[layer]; - } - - @Override - public BlockState getBlock(int x, int y, int z) { - return BlockTypesCache.states[get(x, y, z)]; - } - - @Override - public int getSkyLight(int x, int y, int z) { - return 0; - } - - @Override - public int getEmittedLight(int x, int y, int z) { - return 0; - } - - @Override - public int[] getHeightMap(HeightMapType type) { - return new int[0]; - } - - @Override - public > T call(IChunkSet set, Runnable finalize) { - return null; - } - - public char get(int x, int y, int z) { - final int layer = (y >> 4) - getMinSectionPosition(); - final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; - } - - - @Override - public boolean trim(boolean aggressive) { - return false; - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java deleted file mode 100644 index dbf7f88f3..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java +++ /dev/null @@ -1,663 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; - -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; -import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.math.BitArrayUnstretched; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.mojang.datafixers.util.Either; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import io.papermc.lib.PaperLib; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.IdMap; -import net.minecraft.core.Registry; -import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.BitStorage; -import net.minecraft.util.SimpleBitStorage; -import net.minecraft.util.ThreadingDetector; -import net.minecraft.util.Unit; -import net.minecraft.util.ZeroBitStorage; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.GlobalPalette; -import net.minecraft.world.level.chunk.HashMapPalette; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.LinearPalette; -import net.minecraft.world.level.chunk.Palette; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.chunk.SingleValuePalette; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; -import sun.misc.Unsafe; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Function; - -public final class PaperweightPlatformAdapter extends NMSAdapter { - - public static final Field fieldData; - - public static final Constructor dataConstructor; - - public static final Field fieldStorage; - public static final Field fieldPalette; - - private static final Field fieldTickingFluidCount; - private static final Field fieldTickingBlockCount; - private static final Field fieldNonEmptyBlockCount; - - private static final MethodHandle methodGetVisibleChunk; - - private static final int CHUNKSECTION_BASE; - private static final int CHUNKSECTION_SHIFT; - - private static final Field fieldThreadingDetector; - private static final long fieldThreadingDetectorOffset; - - private static final Field fieldLock; - private static final long fieldLockOffset; - - private static final MethodHandle methodRemoveGameEventListener; - private static final MethodHandle methodremoveTickingBlockEntity; - - private static final Field fieldRemove; - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - static { - try { - fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d")); - fieldData.setAccessible(true); - - Class dataClazz = fieldData.getType(); - dataConstructor = dataClazz.getDeclaredConstructors()[0]; - dataConstructor.setAccessible(true); - - fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b")); - fieldStorage.setAccessible(true); - fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c")); - fieldPalette.setAccessible(true); - - fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h")); - fieldTickingFluidCount.setAccessible(true); - fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g")); - fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f")); - fieldNonEmptyBlockCount.setAccessible(true); - - Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( - "getVisibleChunkIfPresent", - "b" - ), long.class); - getVisibleChunkIfPresent.setAccessible(true); - methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent); - - Unsafe unsafe = ReflectionUtils.getUnsafe(); - if (!PaperLib.isPaper()) { - fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f")); - fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector); - - fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c")); - fieldLockOffset = unsafe.objectFieldOffset(fieldLock); - } else { - // in paper, the used methods are synchronized properly - fieldThreadingDetector = null; - fieldThreadingDetectorOffset = -1; - - fieldLock = null; - fieldLockOffset = -1; - } - - Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( - Refraction.pickName("removeGameEventListener", "d"), - BlockEntity.class - ); - removeGameEventListener.setAccessible(true); - methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener); - Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod( - Refraction.pickName( - "removeBlockEntityTicker", - "l" - ), BlockPos.class - ); - removeBlockEntityTicker.setAccessible(true); - methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker); - - fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); - fieldRemove.setAccessible(true); - - CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class); - int scale = unsafe.arrayIndexScale(LevelChunkSection[].class); - if ((scale & (scale - 1)) != 0) { - throw new Error("data type scale not a power of two"); - } - CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); - } catch (RuntimeException e) { - throw e; - } catch (Throwable rethrow) { - rethrow.printStackTrace(); - throw new RuntimeException(rethrow); - } - } - - static boolean setSectionAtomic( - LevelChunkSection[] sections, - LevelChunkSection expected, - LevelChunkSection value, - int layer - ) { - long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE; - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; - } - - // There is no point in having a functional semaphore for paper servers. - private static final ThreadLocal SEMAPHORE_THREAD_LOCAL = - ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null)); - - static DelegateSemaphore applyLock(LevelChunkSection section) { - if (PaperLib.isPaper()) { - return SEMAPHORE_THREAD_LOCAL.get(); - } - try { - synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); - PalettedContainer blocks = section.getStates(); - ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject( - blocks, - fieldThreadingDetectorOffset - ); - synchronized (currentThreadingDetector) { - Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset); - if (currentLock instanceof DelegateSemaphore delegateSemaphore) { - return delegateSemaphore; - } - DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock); - return newLock; - } - } - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) { - if (!PaperLib.isPaper()) { - LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false); - if (nmsChunk != null) { - return nmsChunk; - } - if (Fawe.isMainThread()) { - return serverLevel.getChunk(chunkX, chunkZ); - } - } else { - LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); - if (nmsChunk != null) { - addTicket(serverLevel, chunkX, chunkZ); - return nmsChunk; - } - nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); - if (nmsChunk != null) { - addTicket(serverLevel, chunkX, chunkZ); - return nmsChunk; - } - // Avoid "async" methods from the main thread. - if (Fawe.isMainThread()) { - return serverLevel.getChunk(chunkX, chunkZ); - } - CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); - try { - CraftChunk chunk; - try { - chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); - } catch (TimeoutException e) { - String world = serverLevel.getWorld().getName(); - // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); - if (loaded) { - LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); - // Retry chunk load - chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); - } else { - throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); - } - } - return chunk.getHandle(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); - } - - private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { - // Ensure chunk is definitely loaded before applying a ticket - net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); - } - - public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { - ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap; - try { - return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ)); - } catch (Throwable thr) { - throw new RuntimeException(thr); - } - } - - @SuppressWarnings("deprecation") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { - ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); - if (chunkHolder == null) { - return; - } - ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ); - // UNLOADED_CHUNK - Optional optional = ((Either) chunkHolder - .getTickingChunkFuture() - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - if (PaperLib.isPaper()) { - // getChunkAtIfLoadedImmediately is paper only - optional = optional.or(() -> Optional.ofNullable(nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ))); - } - if (optional.isEmpty()) { - return; - } - LevelChunk levelChunk = optional.get(); - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true - ); - } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); - } - - private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { - return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false); - } - - /* - NMS conversion - */ - public static LevelChunkSection newChunkSection( - final int layer, - final char[] blocks, - CachedBukkitAdapter adapter, - Registry biomeRegistry, - @Nullable PalettedContainer> biomes - ) { - return newChunkSection(layer, null, blocks, adapter, biomeRegistry, biomes); - } - - public static LevelChunkSection newChunkSection( - final int layer, - final Function get, - char[] set, - CachedBukkitAdapter adapter, - Registry biomeRegistry, - @Nullable PalettedContainer> biomes - ) { - if (set == null) { - return newChunkSection(layer, biomeRegistry, biomes); - } - final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); - final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); - final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get(); - final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get(); - try { - int num_palette; - if (get == null) { - num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, null); - } else { - num_palette = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, get, set, adapter, null); - } - - int bitsPerEntry = MathMan.log2nlz(num_palette - 1); - if (bitsPerEntry > 0 && bitsPerEntry < 5) { - bitsPerEntry = 4; - } else if (bitsPerEntry > 8) { - bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1); - } - - int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes - final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero); - final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong); - - if (num_palette == 1) { - for (int i = 0; i < blockBitArrayEnd; i++) { - blockStates[i] = 0; - } - } else { - final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntryNonZero, 4096, blockStates); - bitArray.fromRaw(blocksCopy); - } - - final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd); - final BitStorage nmsBits; - if (bitsPerEntry == 0) { - nmsBits = new ZeroBitStorage(4096); - } else { - nmsBits = new SimpleBitStorage(bitsPerEntry, 4096, bits); - } - List palette; - if (bitsPerEntry < 9) { - palette = new ArrayList<>(); - for (int i = 0; i < num_palette; i++) { - int ordinal = paletteToBlock[i]; - blockToPalette[ordinal] = Integer.MAX_VALUE; - final BlockState state = BlockTypesCache.states[ordinal]; - palette.add(((PaperweightBlockMaterial) state.getMaterial()).getState()); - } - } else { - palette = List.of(); - } - - // Create palette with data - @SuppressWarnings("deprecation") // constructor is deprecated on paper, but needed to keep compatibility with spigot - final PalettedContainer blockStatePalettedContainer = - new PalettedContainer<>( - Block.BLOCK_STATE_REGISTRY, - PalettedContainer.Strategy.SECTION_STATES, - PalettedContainer.Strategy.SECTION_STATES.getConfiguration(Block.BLOCK_STATE_REGISTRY, bitsPerEntry), - nmsBits, - palette - ); - if (biomes == null) { - IdMap> biomeHolderIdMap = biomeRegistry.asHolderIdMap(); - biomes = new PalettedContainer<>( - biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null - ); - } - - return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); - } catch (final Throwable e) { - throw e; - } finally { - Arrays.fill(blockToPalette, Integer.MAX_VALUE); - Arrays.fill(paletteToBlock, Integer.MAX_VALUE); - Arrays.fill(blockStates, 0); - Arrays.fill(blocksCopy, 0); - } - } - - @SuppressWarnings("deprecation") // Only deprecated in paper - private static LevelChunkSection newChunkSection( - int layer, - Registry biomeRegistry, - @Nullable PalettedContainer> biomes - ) { - if (biomes == null) { - return new LevelChunkSection(layer, biomeRegistry); - } - PalettedContainer dataPaletteBlocks = new PalettedContainer<>( - Block.BLOCK_STATE_REGISTRY, - Blocks.AIR.defaultBlockState(), - PalettedContainer.Strategy.SECTION_STATES, - null - ); - return new LevelChunkSection(layer, dataPaletteBlocks, biomes); - } - - /** - * Create a new {@link PalettedContainer}. Should only be used if no biome container existed beforehand. - */ - public static PalettedContainer> getBiomePalettedContainer( - BiomeType[] biomes, - IdMap> biomeRegistry - ) { - if (biomes == null) { - return null; - } - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - // Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length - Map> palette = new HashMap<>(); - for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) { - Holder biome; - if (biomeType == null) { - biome = biomeRegistry.byId(adapter.getInternalBiomeId(BiomeTypes.PLAINS)); - } else { - biome = biomeRegistry.byId(adapter.getInternalBiomeId(biomeType)); - } - palette.put(biomeType, biome); - } - int biomeCount = palette.size(); - int bitsPerEntry = MathMan.log2nlz(biomeCount - 1); - Object configuration = PalettedContainer.Strategy.SECTION_STATES.getConfiguration( - new FakeIdMapBiome(biomeCount), - bitsPerEntry - ); - if (bitsPerEntry > 3) { - bitsPerEntry = MathMan.log2nlz(biomeRegistry.size() - 1); - } - PalettedContainer> biomePalettedContainer = new PalettedContainer<>( - biomeRegistry, - biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null - ); - - final Palette> biomePalette; - if (bitsPerEntry == 0) { - biomePalette = new SingleValuePalette<>( - biomePalettedContainer.registry, - biomePalettedContainer, - new ArrayList<>(palette.values()) // Must be modifiable - ); - } else if (bitsPerEntry == 4) { - biomePalette = LinearPalette.create( - 4, - biomePalettedContainer.registry, - biomePalettedContainer, - new ArrayList<>(palette.values()) // Must be modifiable - ); - } else if (bitsPerEntry < 9) { - biomePalette = HashMapPalette.create( - bitsPerEntry, - biomePalettedContainer.registry, - biomePalettedContainer, - new ArrayList<>(palette.values()) // Must be modifiable - ); - } else { - biomePalette = GlobalPalette.create( - bitsPerEntry, - biomePalettedContainer.registry, - biomePalettedContainer, - null // unused - ); - } - - int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes - final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero); - final int arrayLength = MathMan.ceilZero(64f / blocksPerLong); - - - BitStorage bitStorage = bitsPerEntry == 0 ? new ZeroBitStorage(64) : new SimpleBitStorage( - bitsPerEntry, - 64, - new long[arrayLength] - ); - - try { - Object data = dataConstructor.newInstance(configuration, bitStorage, biomePalette); - fieldData.set(biomePalettedContainer, data); - int index = 0; - for (int y = 0; y < 4; y++) { - for (int z = 0; z < 4; z++) { - for (int x = 0; x < 4; x++, index++) { - BiomeType biomeType = biomes[index]; - if (biomeType == null) { - continue; - } - Holder biome = biomeRegistry.byId(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)); - if (biome == null) { - continue; - } - biomePalettedContainer.set(x, y, z, biome); - } - } - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - return biomePalettedContainer; - } - - public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException { - fieldTickingFluidCount.setShort(section, (short) 0); - fieldTickingBlockCount.setShort(section, (short) 0); - } - - public static BiomeType adapt(Holder biome, LevelAccessor levelAccessor) { - final Registry biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY); - if (biomeRegistry.getKey(biome.value()) == null) { - return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN - : null; - } - return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString()); - } - - @SuppressWarnings("unchecked") - static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { - try { - // Do the method ourselves to avoid trying to reflect generic method parameters - // similar to removeGameEventListener - if (levelChunk.loaded || levelChunk.level.isClientSide()) { - BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos()); - if (blockEntity != null) { - if (!levelChunk.level.isClientSide) { - methodRemoveGameEventListener.invoke(levelChunk, beacon); - } - fieldRemove.set(beacon, true); - } - } - methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos()); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - } - - static List getEntities(LevelChunk chunk) { - return chunk.level.entityManager.getEntities(chunk.getPos()); - } - - record FakeIdMapBlock(int size) implements IdMap { - - @Override - public int getId(final net.minecraft.world.level.block.state.BlockState entry) { - return 0; - } - - @Nullable - @Override - public net.minecraft.world.level.block.state.BlockState byId(final int index) { - return null; - } - - @Nonnull - @Override - public Iterator iterator() { - return Collections.emptyIterator(); - } - - } - - record FakeIdMapBiome(int size) implements IdMap { - - @Override - public int getId(final Biome entry) { - return 0; - } - - @Nullable - @Override - public Biome byId(final int index) { - return null; - } - - @Nonnull - @Override - public Iterator iterator() { - return Collections.emptyIterator(); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java deleted file mode 100644 index 51bd22bdb..000000000 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java +++ /dev/null @@ -1,541 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field serverWorldsField; - private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - serverWorldsField = CraftServer.class.getDeclaredField("worlds"); - serverWorldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "h")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "g")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "K")); - chunkSourceField.setAccessible(true); - - ringPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("ringPositions", "h")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "i")); - hasGeneratedPositionsField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureManager structureManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - @SuppressWarnings("unchecked") - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - BiomeProvider biomeProvider = getBiomeProvider(); - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldGenSettings originalOpts = originalWorldData.worldGenSettings(); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataPackConfig() - ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - originalServerWorld.dimensionTypeRegistration(), - new RegenNoOpWorldLoadListener(), - // placeholder. Required for new ChunkProviderServer, but we create and then set it later - newOpts.dimensions().getOrThrow(levelStemResourceKey).generator(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - environment, - generator, - biomeProvider - ) { - private final Holder singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ, - PaperweightRegen.this.chunkGenerator.climateSampler() - ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig); - } - - //generator - ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); - if (originalGenerator instanceof FlatLevelSource flatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat); - } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = - (Holder) generatorSettingBaseSupplierField - .get(originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME - .asHolderIdMap() - .byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()))); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, noiseBasedChunkGenerator.noises, - biomeSource, seed, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.delegate; - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator); - if (hasGeneratedPositions) { - Map>> ringPositions = - (Map>>) ringPositionsField.get( - originalGenerator); - Map>> copy = new Object2ObjectArrayMap<>(ringPositions); - ringPositionsField.set(chunkGenerator, copy); - hasGeneratedPositionsField.setBoolean(chunkGenerator, true); - } - } - - - chunkGenerator.conf = originalServerWorld.spigotConfig; - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureManager = server.getStructureManager(); - threadedLevelLightEngine = freshChunkProvider.getLightEngine(); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null - ); - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - public FastProtoChunk( - final ChunkPos pos, - final UpgradeData upgradeData, - final LevelHeightAccessor world, - final Registry biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.getName(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks, - true - ); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightAdapter.java deleted file mode 100644 index 1e8ed0c56..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightAdapter.java +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.PaperweightFaweAdapter; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.platform.Watchdog; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; -import com.sk89q.worldedit.world.DataFixer; -import com.sk89q.worldedit.world.RegenOptions; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.item.ItemType; -import net.minecraft.Util; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.StringRepresentable; -import net.minecraft.util.thread.BlockableEventLoop; -import net.minecraft.world.Clearable; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.StructureBlockEntity; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World.Environment; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_19_R1.CraftServer; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_19_R1.util.CraftMagicNumbers; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.generator.ChunkGenerator; -import org.spigotmc.SpigotConfig; -import org.spigotmc.WatchdogThread; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.OptionalLong; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -public final class PaperweightAdapter implements BukkitImplAdapter { - - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); - - private final Field worldsField; - private final Method getChunkFutureMainThreadMethod; - private final Field mainThreadProcessorField; - private final Watchdog watchdog; - - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ - - public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { - // A simple test - CraftServer.class.cast(Bukkit.getServer()); - - int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 3105 && dataVersion != 3117 && dataVersion != 3120) { - throw new UnsupportedClassVersionError("Not 1.19, 1.19.1 or 1.19.2!"); - } - - worldsField = CraftServer.class.getDeclaredField("worlds"); - worldsField.setAccessible(true); - - getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod( - Refraction.pickName("getChunkFutureMainThread", "c"), - int.class, int.class, ChunkStatus.class, boolean.class - ); - getChunkFutureMainThreadMethod.setAccessible(true); - - mainThreadProcessorField = ServerChunkCache.class.getDeclaredField( - Refraction.pickName("mainThreadProcessor", "g") - ); - mainThreadProcessorField.setAccessible(true); - - new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized(); - - Watchdog watchdog; - try { - Class.forName("org.spigotmc.WatchdogThread"); - watchdog = new SpigotWatchdog(); - } catch (ClassNotFoundException | NoSuchFieldException e) { - try { - watchdog = new MojangWatchdog(((CraftServer) Bukkit.getServer()).getServer()); - } catch (NoSuchFieldException ex) { - watchdog = null; - } - } - this.watchdog = watchdog; - - try { - Class.forName("org.spigotmc.SpigotConfig"); - SpigotConfig.config.set("world-settings.faweregentempworld.verbose", false); - } catch (ClassNotFoundException ignored) { - } - } - - @Override - public DataFixer getDataFixer() { - return PaperweightDataConverters.INSTANCE; - } - - /** - * Read the given NBT data into the given tile entity. - * - * @param tileEntity the tile entity - * @param tag the tag - */ - static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) { - tileEntity.load(tag); - tileEntity.setChanged(); - } - - /** - * Get the ID string of the given entity. - * - * @param entity the entity - * @return the entity ID - */ - private static String getEntityId(Entity entity) { - return EntityType.getKey(entity.getType()).toString(); - } - - /** - * Create an entity using the given entity ID. - * - * @param id the entity ID - * @param world the world - * @return an entity or null - */ - @Nullable - private static Entity createEntityFromId(String id, net.minecraft.world.level.Level world) { - return EntityType.byString(id).map(t -> t.create(world)).orElse(null); - } - - /** - * Write the given NBT data into the given entity. - * - * @param entity the entity - * @param tag the tag - */ - private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { - entity.load(tag); - } - - /** - * Write the entity's NBT data to the given tag. - * - * @param entity the entity - * @param tag the tag - */ - private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) { - entity.save(tag); - } - - private static Block getBlockFromType(BlockType blockType) { - return Registry.BLOCK.get(ResourceLocation.tryParse(blockType.getId())); - } - - private static Item getItemFromType(ItemType itemType) { - return Registry.ITEM.get(ResourceLocation.tryParse(itemType.getId())); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockData data) { - net.minecraft.world.level.block.state.BlockState state = ((CraftBlockData) data).getState(); - int combinedId = Block.getId(state); - return combinedId == 0 && state.getBlock() != Blocks.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); - } - - @Override - public OptionalInt getInternalBlockStateId(BlockState state) { - Block mcBlock = getBlockFromType(state.getBlockType()); - net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); - Map, Object> states = state.getStates(); - newState = applyProperties(mcBlock.getStateDefinition(), newState, states); - final int combinedId = Block.getId(newState); - return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); - } - - @Override - public BlockState getBlock(Location location) { - checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final CraftBlockData blockData = chunk.getBlockState(blockPos).createCraftBlockData(); - BlockState state = BukkitAdapter.adapt(blockData); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; - } - - @Override - public BaseBlock getFullBlock(Location location) { - BlockState state = getBlock(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - - // Read the NBT data - BlockEntity te = chunk.getBlockEntity(blockPos); - if (te != null) { - net.minecraft.nbt.CompoundTag tag = te.saveWithId(); - //FAWE start - BinaryTag - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - //FAWE end - } - - return state.toBaseBlock(); - } - - @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); - } - - private static net.minecraft.core.Direction adapt(Direction face) { - switch (face) { - case NORTH: - return net.minecraft.core.Direction.NORTH; - case SOUTH: - return net.minecraft.core.Direction.SOUTH; - case WEST: - return net.minecraft.core.Direction.WEST; - case EAST: - return net.minecraft.core.Direction.EAST; - case DOWN: - return net.minecraft.core.Direction.DOWN; - case UP: - default: - return net.minecraft.core.Direction.UP; - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private net.minecraft.world.level.block.state.BlockState applyProperties( - StateDefinition stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states - ) { - for (Map.Entry, Object> state : states.entrySet()) { - net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); - Comparable value = (Comparable) state.getValue(); - // we may need to adapt this value, depending on the source prop - if (property instanceof DirectionProperty) { - Direction dir = (Direction) value; - value = adapt(dir); - } else if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - String enumName = (String) value; - value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); - } - - newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value - ); - } - return newState; - } - - @Override - public BaseEntity getEntity(org.bukkit.entity.Entity entity) { - checkNotNull(entity); - - CraftEntity craftEntity = ((CraftEntity) entity); - Entity mcEntity = craftEntity.getHandle(); - - String id = getEntityId(mcEntity); - - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, tag); - //FAWE start - BinaryTag - return new BaseEntity( - com.sk89q.worldedit.world.entity.EntityTypes.get(id), - LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)) - ); - //FAWE end - } - - @Nullable - @Override - public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) { - checkNotNull(location); - checkNotNull(state); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - ServerLevel worldServer = craftWorld.getHandle(); - - Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle()); - - if (createdEntity != null) { - CompoundBinaryTag nativeTag = state.getNbt(); - if (nativeTag != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - readTagIntoEntity(tag, createdEntity); - } - - createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - - worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM); - return createdEntity.getBukkitEntity(); - } else { - return null; - } - } - - @Override - public Component getRichBlockName(BlockType blockType) { - return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); - } - - @Override - public Component getRichItemName(ItemType itemType) { - return TranslatableComponent.of(getItemFromType(itemType).getDescriptionId()); - } - - @Override - public Component getRichItemName(BaseItemStack itemStack) { - return TranslatableComponent.of(CraftItemStack.asNMSCopy(BukkitAdapter.adapt(itemStack)).getDescriptionId()); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); - - @SuppressWarnings({ "rawtypes" }) - @Override - public Map> getProperties(BlockType blockType) { - Map> properties = new TreeMap<>(); - Block block = getBlockFromType(blockType); - StateDefinition blockStateList = - block.getStateDefinition(); - for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { - Property property = PROPERTY_CACHE.getUnchecked(state); - properties.put(property.getName(), property); - } - return properties; - } - - @Override - public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) { - ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create( - new StructureBlockEntity( - new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - Blocks.STRUCTURE_BLOCK.defaultBlockState() - ), - __ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) - )); - } - - @Override - public void sendFakeOP(Player player) { - ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 - )); - } - - @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { - ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); - return CraftItemStack.asCraftMirror(stack); - } - - @Override - public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { - final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; - } - - private final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); - - @Override - public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { - CraftWorld craftWorld = (CraftWorld) world; - ServerLevel worldServer = craftWorld.getHandle(); - ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack - ? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); - stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); - - PaperweightFakePlayer fakePlayer; - try { - fakePlayer = fakePlayers.get(worldServer); - } catch (ExecutionException ignored) { - return false; - } - fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); - fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(), - (float) face.toVector().toYaw(), (float) face.toVector().toPitch() - ); - - final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos); - final net.minecraft.core.Direction enumFacing = adapt(face); - BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false); - UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace); - InteractionResult result = stack.useOn(context, InteractionHand.MAIN_HAND); - if (result != InteractionResult.SUCCESS) { - if (worldServer - .getBlockState(blockPos) - .use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace) - .consumesAction()) { - result = InteractionResult.SUCCESS; - } else { - result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult(); - } - } - - return result == InteractionResult.SUCCESS; - } - - @Override - public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) { - int internalId = BlockStateIdAccess.getBlockStateId(blockState); - net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId); - return blockData.canSurvive( - ((CraftWorld) world).getHandle(), - new BlockPos(position.getX(), position.getY(), position.getZ()) - ); - } - - @Override - public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) { - try { - doRegen(bukkitWorld, region, extent, options); - } catch (Exception e) { - throw new IllegalStateException("Regen failed.", e); - } - - return true; - } - - private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception { - Environment env = bukkitWorld.getEnvironment(); - ChunkGenerator gen = bukkitWorld.getGenerator(); - - Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); - ResourceKey worldDimKey = getWorldDimKey(env); - try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { - ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); - PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() - .getWorldData().overworldData(); - WorldGenSettings originalOpts = levelProperties.worldGenSettings(); - - long seed = options.getSeed().orElse(originalWorld.getSeed()); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) - : originalOpts; - - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - levelProperties.settings.gameType(), - levelProperties.settings.hardcore(), - levelProperties.settings.difficulty(), - levelProperties.settings.allowCommands(), - levelProperties.settings.gameRules(), - levelProperties.settings.getDataPackConfig() - ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); - - ServerLevel freshWorld = new ServerLevel( - originalWorld.getServer(), - originalWorld.getServer().executor, - session, newWorldData, - originalWorld.dimension(), - new LevelStem( - originalWorld.dimensionTypeRegistration(), - newOpts.dimensions().get(worldDimKey).generator() - ), - new NoOpWorldLoadListener(), - originalWorld.isDebug(), - seed, - ImmutableList.of(), - false, - env, - gen, - bukkitWorld.getBiomeProvider() - ); - try { - regenForWorld(region, extent, freshWorld, options); - } finally { - freshWorld.getChunkSource().close(false); - } - } finally { - try { - @SuppressWarnings("unchecked") - Map map = (Map) worldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException ignored) { - } - SafeFiles.tryHardToDeleteDir(tempDir); - } - } - - private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { - ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome); - if (key == null) { - return null; - } - return BiomeTypes.get(key.toString()); - } - - @SuppressWarnings("unchecked") - private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws - WorldEditException { - List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); - BlockableEventLoop executor; - try { - executor = (BlockableEventLoop) mainThreadProcessorField.get(serverWorld.getChunkSource()); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Couldn't get executor for chunk loading.", e); - } - executor.managedBlock(() -> { - // bail out early if a future fails - if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null - )) { - return false; - } - return chunkLoadings.stream().allMatch(CompletableFuture::isDone); - }); - Map chunks = new HashMap<>(); - for (CompletableFuture future : chunkLoadings) { - @Nullable - ChunkAccess chunk = future.getNow(null); - checkState(chunk != null, "Failed to generate a chunk, regen failed."); - chunks.put(chunk.getPos(), chunk); - } - - for (BlockVector3 vec : region) { - BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); - ChunkAccess chunk = chunks.get(new ChunkPos(pos)); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos); - BlockStateHolder state = ((PaperweightFaweAdapter) WorldEditPlugin - .getInstance() - .getBukkitImplAdapter()).adapt(blockData); - Objects.requireNonNull(state); - BlockEntity blockEntity = chunk.getBlockEntity(pos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - //FAWE start - BinaryTag - state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag))); - //FAWE end - } - extent.setBlock(vec, state.toBaseBlock()); - if (options.shouldRegenBiomes()) { - Biome origBiome = chunk.getNoiseBiome(vec.getX(), vec.getY(), vec.getZ()).value(); - BiomeType adaptedBiome = adapt(serverWorld, origBiome); - if (adaptedBiome != null) { - extent.setBiome(vec, adaptedBiome); - } - } - } - } - - @SuppressWarnings("unchecked") - private List> submitChunkLoadTasks(Region region, ServerLevel serverWorld) { - ServerChunkCache chunkManager = serverWorld.getChunkSource(); - List> chunkLoadings = new ArrayList<>(); - // Pre-gen all the chunks - for (BlockVector2 chunk : region.getChunks()) { - try { - chunkLoadings.add( - ((CompletableFuture>) - getChunkFutureMainThreadMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) - ); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("Couldn't load chunk for regen.", e); - } - } - return chunkLoadings; - } - - private ResourceKey getWorldDimKey(Environment env) { - switch (env) { - case NETHER: - return LevelStem.NETHER; - case THE_END: - return LevelStem.END; - case NORMAL: - default: - return LevelStem.OVERWORLD; - } - } - - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE - ); - - @Override - public Set getSupportedSideEffects() { - return SUPPORTED_SIDE_EFFECTS; - } - - @Override - public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) { - ServerLevel originalWorld = ((CraftWorld) world).getHandle(); - - BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ())); - if (entity instanceof Clearable) { - ((Clearable) entity).clearContent(); - return true; - } - return false; - } - - // ------------------------------------------------------------------------ - // Code that is less likely to break - // ------------------------------------------------------------------------ - - /** - * Converts from a non-native NMS NBT structure to a native WorldEdit NBT - * structure. - * - * @param foreign non-native NMS NBT structure - * @return native WorldEdit NBT structure - */ - //FAWE start - BinaryTag - @Override - public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); - Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); - - for (String str : foreignKeys) { - net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); - } - return CompoundBinaryTag.from(values); - } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); - } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); - } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); - } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); - } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); - } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); - } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); - } else if (foreign instanceof net.minecraft.nbt.ListTag) { - try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); - } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); - } - } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); - } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); - } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); - } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); - } - } - - /** - * Convert a foreign NBT list tag into a native WorldEdit one. - * - * @param foreign the foreign tag - * @return the converted tag - * @throws SecurityException on error - * @throws IllegalArgumentException on error - */ - private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { - ListBinaryTag.Builder values = ListBinaryTag.builder(); - - for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); - } - - return values.build(); - } - - /** - * Converts a WorldEdit-native NBT structure to a NMS structure. - * - * @param foreign structure to convert - * @return non-native structure - */ - @Override - public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof CompoundBinaryTag) { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); - } - return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag) { - net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - ListBinaryTag foreignList = (ListBinaryTag) foreign; - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); - } - return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { - return net.minecraft.nbt.EndTag.INSTANCE; - } else { - throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); - } - } - //FAWE end - - @Override - public boolean supportsWatchdog() { - return watchdog != null; - } - - @Override - public void tickWatchdog() { - watchdog.tick(); - } - - private class SpigotWatchdog implements Watchdog { - - private final Field instanceField; - private final Field lastTickField; - - SpigotWatchdog() throws NoSuchFieldException { - Field instanceField = WatchdogThread.class.getDeclaredField("instance"); - instanceField.setAccessible(true); - this.instanceField = instanceField; - - Field lastTickField = WatchdogThread.class.getDeclaredField("lastTick"); - lastTickField.setAccessible(true); - this.lastTickField = lastTickField; - } - - @Override - public void tick() { - try { - WatchdogThread instance = (WatchdogThread) this.instanceField.get(null); - if ((long) lastTickField.get(instance) != 0) { - WatchdogThread.tick(); - } - } catch (IllegalAccessException e) { - LOGGER.log(Level.WARNING, "Failed to tick watchdog", e); - } - } - - } - - private static class MojangWatchdog implements Watchdog { - - private final DedicatedServer server; - private final Field tickField; - - MojangWatchdog(DedicatedServer server) throws NoSuchFieldException { - this.server = server; - Field tickField = MinecraftServer.class.getDeclaredField( - Refraction.pickName("nextTickTime", "ag") - ); - if (tickField.getType() != long.class) { - throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect"); - } - tickField.setAccessible(true); - this.tickField = tickField; - } - - @Override - public void tick() { - try { - tickField.set(server, Util.getMillis()); - } catch (IllegalAccessException ignored) { - } - } - - } - - private static class NoOpWorldLoadListener implements ChunkProgressListener { - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - } - - @Override - public void stop() { - } - - @Override - public void setChunkRadius(int radius) { - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightBlockMaterial.java deleted file mode 100644 index 812cd4e24..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightBlockMaterial.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; - -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.util.ReflectionUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.world.registry.BlockMaterial; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.EmptyBlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.PushReaction; -import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; - -public class PaperweightBlockMaterial implements BlockMaterial { - - private final Block block; - private final BlockState blockState; - private final Material material; - private final boolean isTranslucent; - private final CraftBlockData craftBlockData; - private final org.bukkit.Material craftMaterial; - private final int opacity; - private final CompoundTag tile; - - public PaperweightBlockMaterial(Block block) { - this(block, block.defaultBlockState()); - } - - public PaperweightBlockMaterial(Block block, BlockState blockState) { - this.block = block; - this.blockState = blockState; - this.material = blockState.getMaterial(); - this.craftBlockData = CraftBlockData.fromData(blockState); - this.craftMaterial = craftBlockData.getMaterial(); - BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName( - "properties", "aO")); - this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo, - Refraction.pickName("canOcclude", "n") - ); - opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); - BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( - BlockPos.ZERO, - blockState - ); - tile = tileEntity == null - ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); - } - - public Block getBlock() { - return block; - } - - public BlockState getState() { - return blockState; - } - - public CraftBlockData getCraftBlockData() { - return craftBlockData; - } - - public Material getMaterial() { - return material; - } - - @Override - public boolean isAir() { - return blockState.isAir(); - } - - @Override - public boolean isFullCube() { - return craftMaterial.isOccluding(); - } - - @Override - public boolean isOpaque() { - return material.isSolidBlocking(); - } - - @Override - public boolean isPowerSource() { - return blockState.isSignalSource(); - } - - @Override - public boolean isLiquid() { - return material.isLiquid(); - } - - @Override - public boolean isSolid() { - return material.isSolid(); - } - - @Override - public float getHardness() { - return craftBlockData.getState().destroySpeed; - } - - @Override - public float getResistance() { - return block.getExplosionResistance(); - } - - @Override - public float getSlipperiness() { - return block.getFriction(); - } - - @Override - public int getLightValue() { - return blockState.getLightEmission(); - } - - @Override - public int getLightOpacity() { - return opacity; - } - - @Override - public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; - } - - @Override - public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; - } - - @Override - public boolean isTicksRandomly() { - return block.isRandomlyTicking(blockState); - } - - @Override - public boolean isMovementBlocker() { - return material.isSolid(); - } - - @Override - public boolean isBurnable() { - return material.isFlammable(); - } - - @Override - public boolean isToolRequired() { - // Removed in 1.16.1, this is not present in higher versions - return false; - } - - @Override - public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); - } - - @Override - public boolean isTranslucent() { - return isTranslucent; - } - - @Override - public boolean hasContainer() { - return block instanceof EntityBlock; - } - - @Override - public boolean isTile() { - return block instanceof EntityBlock; - } - - @Override - public CompoundTag getDefaultTile() { - return tile; - } - - @Override - public int getMapColor() { - // rgb field - return material.getColor().col; - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweWorldNativeAccess.java deleted file mode 100644 index 0e7f6ea0c..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweWorldNativeAccess.java +++ /dev/null @@ -1,286 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; - -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.math.IntPair; -import com.fastasyncworldedit.core.util.TaskManager; -import com.fastasyncworldedit.core.util.task.RunnableVal; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.world.block.BlockState; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; -import org.bukkit.event.block.BlockPhysicsEvent; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess { - - private static final int UPDATE = 1; - private static final int NOTIFY = 2; - private static final Direction[] NEIGHBOUR_ORDER = { - Direction.EAST, - Direction.WEST, - Direction.DOWN, - Direction.UP, - Direction.NORTH, - Direction.SOUTH - }; - private final PaperweightFaweAdapter paperweightFaweAdapter; - private final WeakReference level; - private final AtomicInteger lastTick; - private final Set cachedChanges = new HashSet<>(); - private final Set cachedChunksToSend = new HashSet<>(); - private SideEffectSet sideEffectSet; - - public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { - this.paperweightFaweAdapter = paperweightFaweAdapter; - this.level = level; - // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. - // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - this.lastTick = new AtomicInteger(MinecraftServer.currentTick); - } - - private Level getLevel() { - return Objects.requireNonNull(level.get(), "The reference to the world was lost"); - } - - @Override - public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { - this.sideEffectSet = sideEffectSet; - } - - @Override - public LevelChunk getChunk(int x, int z) { - return getLevel().getChunk(x, z); - } - - @Override - public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) { - int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar()); - return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState(); - } - - @Override - public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) { - return levelChunk.getBlockState(blockPos); - } - - @Nullable - @Override - public synchronized net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk levelChunk, BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState blockState - ) { - int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { - return levelChunk.setBlockState(blockPos, blockState, - this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) - ); - } - // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) - cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ())); - boolean nextTick = lastTick.get() > currentTick; - if (nextTick || cachedChanges.size() >= 1024) { - if (nextTick) { - lastTick.set(currentTick); - } - flushAsync(nextTick); - } - return blockState; - } - - @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState blockState, - BlockPos blockPos - ) { - return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos); - } - - @Override - public BlockPos getPosition(int x, int y, int z) { - return new BlockPos(x, y, z); - } - - @Override - public void updateLightingForBlock(BlockPos blockPos) { - getLevel().getChunkSource().getLightEngine().checkBlock(blockPos); - } - - @Override - public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) { - // We will assume that the tile entity was created for us, - // though we do not do this on the other versions - BlockEntity blockEntity = getLevel().getBlockEntity(blockPos); - if (blockEntity == null) { - return false; - } - net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag); - blockEntity.load((CompoundTag) nativeTag); - return true; - } - - @Override - public void notifyBlockUpdate( - LevelChunk levelChunk, BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { - getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY); - } - } - - @Override - public boolean isChunkTicking(LevelChunk levelChunk) { - return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - } - - @Override - public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) { - if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { - ((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos); - } - } - - @Override - public void notifyNeighbors( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - Level level = getLevel(); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - level.blockUpdated(blockPos, oldState.getBlock()); - } else { - // When we don't want events, manually run the physics without them. - // Un-nest neighbour updating - for (Direction direction : NEIGHBOUR_ORDER) { - BlockPos shifted = blockPos.relative(direction); - level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false); - } - } - if (newState.hasAnalogOutputSignal()) { - level.updateNeighbourForOutputSignal(blockPos, newState.getBlock()); - } - } - - @Override - public void updateNeighbors( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { - Level level = getLevel(); - // a == updateNeighbors - // b == updateDiagonalNeighbors - oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); - if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { - CraftWorld craftWorld = level.getWorld(); - if (craftWorld != null) { - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), - CraftBlockData.fromData(newState) - ); - level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } - } - newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit); - newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); - } - - @Override - public void onBlockStateChange( - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { - getLevel().onBlockStateChange(blockPos, oldState, newState); - } - - private synchronized void flushAsync(final boolean sendChunks) { - final Set changes = Set.copyOf(cachedChanges); - cachedChanges.clear(); - final Set toSend; - if (sendChunks) { - toSend = Set.copyOf(cachedChunksToSend); - cachedChunksToSend.clear(); - } else { - toSend = Collections.emptySet(); - } - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - if (!sendChunks) { - return; - } - for (IntPair chunk : toSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); - } - - @Override - public synchronized void flush() { - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - for (IntPair chunk : cachedChunksToSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - if (Fawe.isMainThread()) { - runnableVal.run(); - } else { - TaskManager.taskManager().sync(runnableVal); - } - cachedChanges.clear(); - cachedChunksToSend.clear(); - } - - private record CachedChange( - LevelChunk levelChunk, - BlockPos blockPos, - net.minecraft.world.level.block.state.BlockState blockState - ) { - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightMapChunkUtil.java deleted file mode 100644 index ead60b212..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightMapChunkUtil.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; - -import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData; - -import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; - -//TODO un-very-break-this -public class PaperweightMapChunkUtil extends MapChunkUtil { - - public PaperweightMapChunkUtil() throws NoSuchFieldException { - fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a")); - fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a")); - fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b")); - fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b")); - fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c")); - fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c")); - fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d")); - fieldX.setAccessible(true); - fieldZ.setAccessible(true); - fieldBitMask.setAccessible(true); - fieldHeightMap.setAccessible(true); - fieldChunkData.setAccessible(true); - fieldBlockEntities.setAccessible(true); - fieldFull.setAccessible(true); - } - - @Override - public ClientboundLevelChunkWithLightPacket createPacket() { - // TODO ??? return new ClientboundLevelChunkPacket(); - throw new UnsupportedOperationException(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java deleted file mode 100644 index 8e1e763b1..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.TaskManager; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.IntConsumer; - -public class PaperweightStarlightRelighter implements Relighter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 - private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); - - - private final ServerLevel serverLevel; - private final ReentrantLock lock = new ReentrantLock(); - private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); - private final ReentrantLock areaLock = new ReentrantLock(); - private final NMSRelighter delegate; - - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { - this.serverLevel = serverLevel; - this.delegate = new NMSRelighter(queue); - } - - @Override - public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { - areaLock.lock(); - try { - long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); - // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? - LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); - } finally { - areaLock.unlock(); - } - return true; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - - /* - * This method is called "recursively", iterating and removing elements - * from the regions linked map. This way, chunks are loaded in batches to avoid - * OOMEs. - */ - @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } - } - - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); - } catch (Exception e) { - LOGGER.error("Error occurred on relighting", e); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - this.delegate.removeLighting(); - } - - @Override - public void fixBlockLighting() { - fixLightingSafe(true); - } - - @Override - public void fixSkyLighting() { - fixLightingSafe(true); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ReentrantLock getLock() { - return this.lock; - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void close() throws Exception { - fixLightingSafe(true); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java deleted file mode 100644 index ebe096996..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java +++ /dev/null @@ -1,564 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R1.CraftServer; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field serverWorldsField; - private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - serverWorldsField = CraftServer.class.getDeclaredField("worlds"); - serverWorldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "g")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "f")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "L")); - chunkSourceField.setAccessible(true); - - ringPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("ringPositions", "i")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "j")); - hasGeneratedPositionsField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureTemplateManager structureTemplateManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - @SuppressWarnings("unchecked") - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldGenSettings originalOpts = originalWorldData.worldGenSettings(); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataPackConfig() - ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); - - BiomeProvider biomeProvider = getBiomeProvider(); - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - newOpts.dimensions().getOrThrow(levelStemResourceKey), - new RegenNoOpWorldLoadListener(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - environment, - generator, - biomeProvider - ) { - private final Holder singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); - } - - ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); - if (originalGenerator instanceof FlatLevelSource flatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat); - } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME - .asHolderIdMap() - .byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()))); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, - noiseBasedChunkGenerator.noises, - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } - chunkGenerator.conf = freshWorld.spigotConfig; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator); - if (hasGeneratedPositions) { - Map>> ringPositions = - (Map>>) ringPositionsField.get( - originalGenerator); - Map>> copy = new Object2ObjectArrayMap<>(ringPositions); - ringPositionsField.set(chunkGenerator, copy); - hasGeneratedPositionsField.setBoolean(chunkGenerator, true); - } - } - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null - ); - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - public FastProtoChunk( - final ChunkPos pos, - final UpgradeData upgradeData, - final LevelHeightAccessor world, - final Registry biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.getName(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks, - true - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> {}, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> {}); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture retainData(final ChunkAccess chunk) { - return CompletableFuture.completedFuture(chunk); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighter.java deleted file mode 100644 index 642250aa0..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighter.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.TaskManager; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.IntConsumer; - -public class PaperweightStarlightRelighter implements Relighter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 - private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); - - - private final ServerLevel serverLevel; - private final ReentrantLock lock = new ReentrantLock(); - private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); - private final ReentrantLock areaLock = new ReentrantLock(); - private final NMSRelighter delegate; - - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { - this.serverLevel = serverLevel; - this.delegate = new NMSRelighter(queue); - } - - @Override - public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { - areaLock.lock(); - try { - long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); - // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? - LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); - } finally { - areaLock.unlock(); - } - return true; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - - /* - * This method is called "recursively", iterating and removing elements - * from the regions linked map. This way, chunks are loaded in batches to avoid - * OOMEs. - */ - @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } - } - - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); - } catch (Exception e) { - LOGGER.error("Error occurred on relighting", e); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - this.delegate.removeLighting(); - } - - @Override - public void fixBlockLighting() { - fixLightingSafe(true); - } - - @Override - public void fixSkyLighting() { - fixLightingSafe(true); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ReentrantLock getLock() { - return this.lock; - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void close() throws Exception { - fixLightingSafe(true); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/regen/PaperweightRegen.java deleted file mode 100644 index 74dccf63b..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/regen/PaperweightRegen.java +++ /dev/null @@ -1,594 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R2.CraftServer; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R2.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import static net.minecraft.core.registries.Registries.BIOME; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field serverWorldsField; - private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - serverWorldsField = CraftServer.class.getDeclaredField("worlds"); - serverWorldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "e")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "L")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "w")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureTemplateManager structureTemplateManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - @SuppressWarnings("unchecked") - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldOptions originalOpts = originalWorldData.worldGenOptions(); - WorldOptions newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataConfiguration() - ); - - PrimaryLevelData.SpecialWorldProperty specialWorldProperty = - originalWorldData.isFlatWorld() - ? PrimaryLevelData.SpecialWorldProperty.FLAT - : originalWorldData.isDebugWorld() - ? PrimaryLevelData.SpecialWorldProperty.DEBUG - : PrimaryLevelData.SpecialWorldProperty.NONE; - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); - - BiomeProvider biomeProvider = getBiomeProvider(); - - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow() - .getOrThrow(levelStemResourceKey), - new RegenNoOpWorldLoadListener(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - environment, - generator, - biomeProvider - ) { - - private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); - } - - ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); - if (originalGenerator instanceof FlatLevelSource flatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(generatorSettingFlat); - } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(BIOME), null - ); - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - public FastProtoChunk( - final ChunkPos pos, - final UpgradeData upgradeData, - final LevelHeightAccessor world, - final Registry biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.getName(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks, - true - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture retainData(final ChunkAccess chunk) { - return CompletableFuture.completedFuture(chunk); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java deleted file mode 100644 index 62d781212..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.TaskManager; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.IntConsumer; - -public class PaperweightStarlightRelighter implements Relighter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 - private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); - - - private final ServerLevel serverLevel; - private final ReentrantLock lock = new ReentrantLock(); - private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); - private final ReentrantLock areaLock = new ReentrantLock(); - private final NMSRelighter delegate; - - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { - this.serverLevel = serverLevel; - this.delegate = new NMSRelighter(queue); - } - - @Override - public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { - areaLock.lock(); - try { - long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); - // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? - LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); - } finally { - areaLock.unlock(); - } - return true; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - - /* - * This method is called "recursively", iterating and removing elements - * from the regions linked map. This way, chunks are loaded in batches to avoid - * OOMEs. - */ - @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } - } - - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); - } catch (Exception e) { - LOGGER.error("Error occurred on relighting", e); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - this.delegate.removeLighting(); - } - - @Override - public void fixBlockLighting() { - fixLightingSafe(true); - } - - @Override - public void fixSkyLighting() { - fixLightingSafe(true); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ReentrantLock getLock() { - return this.lock; - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void close() throws Exception { - fixLightingSafe(true); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java deleted file mode 100644 index 4f22e8734..000000000 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java +++ /dev/null @@ -1,599 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.craftbukkit.v1_19_R3.CraftServer; -import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R3.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import static net.minecraft.core.registries.Registries.BIOME; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field serverWorldsField; - private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - serverWorldsField = CraftServer.class.getDeclaredField("worlds"); - serverWorldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "e")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "M")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "w")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureTemplateManager structureTemplateManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - @SuppressWarnings("unchecked") - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldOptions originalOpts = originalWorldData.worldGenOptions(); - WorldOptions newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataConfiguration() - ); - - PrimaryLevelData.SpecialWorldProperty specialWorldProperty = - originalWorldData.isFlatWorld() - ? PrimaryLevelData.SpecialWorldProperty.FLAT - : originalWorldData.isDebugWorld() - ? PrimaryLevelData.SpecialWorldProperty.DEBUG - : PrimaryLevelData.SpecialWorldProperty.NONE; - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); - - BiomeProvider biomeProvider = getBiomeProvider(); - - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow() - .getOrThrow(levelStemResourceKey), - new RegenNoOpWorldLoadListener(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - environment, - generator, - biomeProvider - ) { - - private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); - } - - ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); - if (originalGenerator instanceof FlatLevelSource flatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(generatorSettingFlat); - } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(BIOME), null - ); - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - public FastProtoChunk( - final ChunkPos pos, - final UpgradeData upgradeData, - final LevelHeightAccessor world, - final Registry biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.getName(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks, - true - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture retainData(final ChunkAccess chunk) { - return CompletableFuture.completedFuture(chunk); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20/build.gradle.kts deleted file mode 100644 index 2f65af4ce..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension - -plugins { - java -} - -applyPaperweightAdapterConfiguration() - -repositories { - gradlePluginPortal() -} - -dependencies { - // https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ - the().paperDevBundle("1.20.1-R0.1-20230818.021330-113") - compileOnly(libs.paperlib) -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPostProcessor.java deleted file mode 100644 index 0c4bcff85..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPostProcessor.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.fastasyncworldedit.core.queue.IChunk; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.registry.state.PropertyKey; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.Fluids; - -import javax.annotation.Nullable; - -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } - - @SuppressWarnings("deprecation") - @Override - public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) { - boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS; - // The PostProcessor shouldn't be added, but just in case - if (!tickFluid) { - return; - } - PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; - layer: - for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); - if (set == null) { - // No edit means no need to process - continue; - } - char[] get = null; - for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; - char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; - boolean fromGet = false; // Used for liquids - if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { - if (get == null) { - get = getBlocks.load(layer); - } - // If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't - // actually being set - if (get == null) { - continue layer; - } - fromGet = true; - ordinal = replacedOrdinal = get[i]; - } - if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { - continue; - } else if (!fromGet) { // if fromGet, don't do the same again - if (get == null) { - get = getBlocks.load(layer); - } - replacedOrdinal = get[i]; - } - boolean ticking = BlockTypesCache.ticking[ordinal]; - boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; - boolean replacedWasLiquid = false; - BlockState replacedState = null; - if (!ticking) { - // If the block being replaced was not ticking, it cannot be a liquid - if (!replacedWasTicking) { - continue; - } - // If the block being replaced is not fluid, we do not need to worry - if (!(replacedWasLiquid = - (replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) { - continue; - } - } - BlockState state = BlockState.getFromOrdinal(ordinal); - boolean liquid = state.getMaterial().isLiquid(); - int x = i & 15; - int y = (i >> 8) & 15; - int z = (i >> 4) & 15; - BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z); - if (liquid || replacedWasLiquid) { - if (liquid) { - addFluid(getBlocks.serverLevel, state, position); - continue; - } - // If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this - // may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up - // being ticked anyway. We only need it to be "hit" once. - if (!wasAdjacentToWater(get, set, i, x, y, z)) { - continue; - } - addFluid(getBlocks.serverLevel, replacedState, position); - } - } - } - } - - @Nullable - @Override - public Extent construct(final Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } - - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - - @SuppressWarnings("deprecation") - private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { - Fluid type; - if (replacedState.getBlockType() == BlockTypes.LAVA) { - type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA; - } else { - type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER; - } - serverLevel.scheduleTick( - position, - type, - type.getTickDelay(serverLevel) - ); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java deleted file mode 100644 index 2cc67360b..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; - -import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.TaskManager; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.IntConsumer; - -public class PaperweightStarlightRelighter implements Relighter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 - private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); - - - private final ServerLevel serverLevel; - private final ReentrantLock lock = new ReentrantLock(); - private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); - private final ReentrantLock areaLock = new ReentrantLock(); - private final NMSRelighter delegate; - - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { - this.serverLevel = serverLevel; - this.delegate = new NMSRelighter(queue); - } - - @Override - public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { - areaLock.lock(); - try { - long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); - // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? - LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); - } finally { - areaLock.unlock(); - } - return true; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - - /* - * This method is called "recursively", iterating and removing elements - * from the regions linked map. This way, chunks are loaded in batches to avoid - * OOMEs. - */ - @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } - } - - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); - } catch (Exception e) { - LOGGER.error("Error occurred on relighting", e); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - this.delegate.removeLighting(); - } - - @Override - public void fixBlockLighting() { - fixLightingSafe(true); - } - - @Override - public void fixSkyLighting() { - fixLightingSafe(true); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ReentrantLock getLock() { - return this.lock; - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void close() throws Exception { - fixLightingSafe(true); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighterFactory.java deleted file mode 100644 index e2658ee0e..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighterFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; - -import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; -import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; -import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.sk89q.worldedit.world.World; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; - -import javax.annotation.Nonnull; - -public class PaperweightStarlightRelighterFactory implements RelighterFactory { - - @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { - org.bukkit.World w = Bukkit.getWorld(world.getName()); - if (w == null) { - return NullRelighter.INSTANCE; - } - return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/nbt/PaperweightLazyCompoundTag.java deleted file mode 100644 index dbdece689..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/nbt/PaperweightLazyCompoundTag.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.LazyCompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import net.minecraft.nbt.NumericTag; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -public class PaperweightLazyCompoundTag extends LazyCompoundTag { - - private final Supplier compoundTagSupplier; - private CompoundTag compoundTag; - - public PaperweightLazyCompoundTag(Supplier compoundTagSupplier) { - super(new HashMap<>()); - this.compoundTagSupplier = compoundTagSupplier; - } - - public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) { - this(() -> compoundTag); - } - - public net.minecraft.nbt.CompoundTag get() { - return compoundTagSupplier.get(); - } - - @Override - @SuppressWarnings("unchecked") - public Map getValue() { - if (compoundTag == null) { - compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); - } - return compoundTag.getValue(); - } - - @Override - public CompoundBinaryTag asBinaryTag() { - getValue(); - return compoundTag.asBinaryTag(); - } - - public boolean containsKey(String key) { - return compoundTagSupplier.get().contains(key); - } - - public byte[] getByteArray(String key) { - return compoundTagSupplier.get().getByteArray(key); - } - - public byte getByte(String key) { - return compoundTagSupplier.get().getByte(key); - } - - public double getDouble(String key) { - return compoundTagSupplier.get().getDouble(key); - } - - public double asDouble(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsDouble(); - } - return 0; - } - - public float getFloat(String key) { - return compoundTagSupplier.get().getFloat(key); - } - - public int[] getIntArray(String key) { - return compoundTagSupplier.get().getIntArray(key); - } - - public int getInt(String key) { - return compoundTagSupplier.get().getInt(key); - } - - public int asInt(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsInt(); - } - return 0; - } - - @SuppressWarnings("unchecked") - public List getList(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); - for (net.minecraft.nbt.Tag elem : nbtList) { - if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { - list.add(new PaperweightLazyCompoundTag(compoundTag)); - } else { - list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem)); - } - } - return list; - } - return Collections.emptyList(); - } - - @SuppressWarnings("unchecked") - public ListTag getListTag(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof net.minecraft.nbt.ListTag) { - return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag); - } - return new ListTag(StringTag.class, Collections.emptyList()); - } - - @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { - ListTag listTag = getListTag(key); - if (listTag.getType().equals(listType)) { - return (List) listTag.getValue(); - } else { - return Collections.emptyList(); - } - } - - public long[] getLongArray(String key) { - return compoundTagSupplier.get().getLongArray(key); - } - - public long getLong(String key) { - return compoundTagSupplier.get().getLong(key); - } - - public long asLong(String key) { - net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); - if (tag instanceof NumericTag numTag) { - return numTag.getAsLong(); - } - return 0; - } - - public short getShort(String key) { - return compoundTagSupplier.get().getShort(key); - } - - public String getString(String key) { - return compoundTagSupplier.get().getString(key); - } - - @Override - public String toString() { - return compoundTagSupplier.get().toString(); - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java deleted file mode 100644 index b5d5a2733..000000000 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java +++ /dev/null @@ -1,594 +0,0 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.regen; - -import com.fastasyncworldedit.bukkit.adapter.Regenerator; -import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.queue.IChunkCache; -import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Lifecycle; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.PaperweightGetBlocks; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.generator.CustomChunkGenerator; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; - -import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import static net.minecraft.core.registries.Registries.BIOME; - -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static final Field serverWorldsField; - private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; - private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); - - static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - /*chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results*/ - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - // chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - - try { - serverWorldsField = CraftServer.class.getDeclaredField("worlds"); - serverWorldsField.setAccessible(true); - - Field tmpPaperConfigField; - Field tmpFlatBedrockField; - try { //only present on paper - tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); - tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); - } catch (Exception e) { - tmpPaperConfigField = null; - tmpFlatBedrockField = null; - } - paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; - - generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( - "settings", "e")); - generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //runtime - private ServerLevel originalServerWorld; - private ServerChunkCache originalChunkProvider; - private ServerLevel freshWorld; - private ServerChunkCache freshChunkProvider; - private LevelStorageSource.LevelStorageAccess session; - private StructureTemplateManager structureTemplateManager; - private ThreadedLevelLightEngine threadedLevelLightEngine; - private ChunkGenerator chunkGenerator; - - private Path tempDir; - - private boolean generateFlatBedrock = false; - - public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) { - super(originalBukkitWorld, region, target, options); - } - - @Override - protected boolean prepare() { - this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); - originalChunkProvider = originalServerWorld.getChunkSource(); - if (!(originalChunkProvider instanceof ServerChunkCache)) { - return false; - } - - //flat bedrock? (only on paper) - if (paperConfigField != null) { - try { - generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); - } catch (Exception ignored) { - } - } - - seed = options.getSeed().orElse(originalServerWorld.getSeed()); - chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c)); - - return true; - } - - @Override - @SuppressWarnings("unchecked") - protected boolean initNewWorld() throws Exception { - //world folder - tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); - - //prepare for world init (see upstream implementation for reference) - org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); - org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); - LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); - ResourceKey levelStemResourceKey = getWorldDimKey(environment); - session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); - PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; - - MinecraftServer server = originalServerWorld.getCraftServer().getServer(); - WorldOptions originalOpts = originalWorldData.worldGenOptions(); - WorldOptions newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(OptionalLong.of(seed)) - : originalOpts; - LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - originalWorldData.settings.gameType(), - originalWorldData.settings.hardcore(), - originalWorldData.settings.difficulty(), - originalWorldData.settings.allowCommands(), - originalWorldData.settings.gameRules(), - originalWorldData.settings.getDataConfiguration() - ); - - PrimaryLevelData.SpecialWorldProperty specialWorldProperty = - originalWorldData.isFlatWorld() - ? PrimaryLevelData.SpecialWorldProperty.FLAT - : originalWorldData.isDebugWorld() - ? PrimaryLevelData.SpecialWorldProperty.DEBUG - : PrimaryLevelData.SpecialWorldProperty.NONE; - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); - - BiomeProvider biomeProvider = getBiomeProvider(); - - - //init world - freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( - server, - server.executor, - session, - newWorldData, - originalServerWorld.dimension(), - DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow() - .getOrThrow(levelStemResourceKey), - new RegenNoOpWorldLoadListener(), - originalServerWorld.isDebug(), - seed, - ImmutableList.of(), - false, - originalServerWorld.getRandomSequences(), - environment, - generator, - biomeProvider - ) { - - private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking - } - - @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - if (options.hasBiomeType()) { - return singleBiome; - } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); - } - }).get(); - freshWorld.noSave = true; - removeWorldFromWorldsMap(); - newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name - if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); - } - - ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); - if (originalGenerator instanceof FlatLevelSource flatLevelSource) { - FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(generatorSettingFlat); - } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - return true; - } - - @Override - protected void cleanup() { - try { - session.close(); - } catch (Exception ignored) { - } - - //shutdown chunk provider - try { - Fawe.instance().getQueueHandler().sync(() -> { - try { - freshChunkProvider.close(false); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } catch (Exception ignored) { - } - - //remove world from server - try { - Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); - } catch (Exception ignored) { - } - - //delete directory - try { - SafeFiles.tryHardToDeleteDir(tempDir); - } catch (Exception ignored) { - } - } - - @Override - protected ProtoChunk createProtoChunk(int x, int z) { - return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(BIOME), null - ); - } - - @Override - protected LevelChunk createChunk(ProtoChunk protoChunk) { - return new LevelChunk( - freshWorld, - protoChunk, - null // we don't want to add entities - ); - } - - @Override - protected ChunkStatusWrap getFullChunkStatus() { - return new ChunkStatusWrap(ChunkStatus.FULL); - } - - @Override - protected List getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - - @Override - protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; - } - - //util - @SuppressWarnings("unchecked") - private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { - return switch (env) { - case NETHER -> LevelStem.NETHER; - case THE_END -> LevelStem.END; - default -> LevelStem.OVERWORLD; - }; - } - - private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { - - private RegenNoOpWorldLoadListener() { - } - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { - } - - @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { - } - - @Override - public void start() { - - } - - @Override - public void stop() { - } - - // TODO Paper only(?) @Override - public void setChunkRadius(int radius) { - } - - } - - private class FastProtoChunk extends ProtoChunk { - - public FastProtoChunk( - final ChunkPos pos, - final UpgradeData upgradeData, - final LevelHeightAccessor world, - final Registry biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.toString(); - } - - @Override - public CompletableFuture processChunk(Long xz, List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - -} diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts similarity index 64% rename from worldedit-bukkit/adapters/adapter-1_19_4/build.gradle.kts rename to worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts index df27ae5d6..995446059 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts @@ -11,6 +11,7 @@ repositories { } dependencies { - the().paperDevBundle("1.19.4-R0.1-20230608.201059-104") + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.2-R0.1-SNAPSHOT + the().paperDevBundle("1.20.2-R0.1-20231203.034718-121") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java similarity index 65% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java index ddaa2c6b4..9aaeb7bc2 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java @@ -17,31 +17,18 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.EndTag; -import com.sk89q.jnbt.FloatTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongArrayTag; -import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.NBTConstants; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; @@ -68,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeCategory; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; @@ -94,6 +68,9 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.item.ItemType; import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; @@ -105,6 +82,7 @@ import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.RandomSource; import net.minecraft.util.StringRepresentable; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Clearable; @@ -135,21 +113,39 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_19_R2.CraftServer; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_19_R2.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.v1_20_R2.CraftServer; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.generator.ChunkGenerator; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinEndTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -157,6 +153,7 @@ import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -171,20 +168,21 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public final class PaperweightAdapter implements BukkitImplAdapter { - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); private final Field serverWorldsField; private final Method getChunkFutureMethod; private final Field chunkProviderExecutorField; private final Watchdog watchdog; + private static final RandomSource random = RandomSource.create(); + // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ @@ -194,21 +192,21 @@ public final class PaperweightAdapter implements BukkitImplAdapter> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - int internalId = Block.getId(blockData); - BlockState state = BlockStateIdAccess.getBlockStateById(internalId); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; + return adapt(blockData); } @Override @@ -358,16 +371,50 @@ public final class PaperweightAdapter implements BukkitImplAdapter> biomeTypeToNMSCache = new HashMap<>(); + private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); + @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { + public BiomeType getBiome(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + + return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString())); + } + + @Override + public void setBiome(Location location, BiomeType biome) { + checkNotNull(location); + checkNotNull(biome); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id()))))); + chunk.setUnsaved(true); + } + + @Override + public WorldNativeAccess createWorldNativeAccess(World world) { return new PaperweightWorldNativeAccess(this, - new WeakReference<>(((CraftWorld) world).getHandle())); + new WeakReference<>(((CraftWorld) world).getHandle())); } private static net.minecraft.core.Direction adapt(Direction face) { @@ -390,13 +437,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states + StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, + Map, Object> states ) { for (Map.Entry, Object> state : states.entrySet()) { net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); + stateContainer.getProperty(state.getKey().getName()); Comparable value = (Comparable) state.getValue(); // we may need to adapt this value, depending on the source prop if (property instanceof DirectionProperty) { @@ -405,16 +452,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); + .getValue(enumName).orElseThrow(() -> + new IllegalStateException( + "Enum property " + property.getName() + " does not contain " + enumName + ) + ); } newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value + (net.minecraft.world.level.block.state.properties.Property) property, + (Comparable) value ); } return newState; @@ -438,7 +485,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter (CompoundBinaryTag) toNativeBinary(tag)) + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)) ); } @@ -451,12 +498,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); + private static final LoadingCache> PROPERTY_CACHE = CacheBuilder + .newBuilder() + .build(new CacheLoader<>() { + @Override + public Property load(net.minecraft.world.level.block.state.properties.Property state) { + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + return new DirectionalProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> Direction.valueOf(((StringRepresentable) e) + .getSerializedName() + .toUpperCase(Locale.ROOT))) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + return new EnumProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> ((StringRepresentable) e).getSerializedName()) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state + .getClass() + .getSimpleName()); + } + } + }); @SuppressWarnings({ "rawtypes" }) @Override @@ -529,7 +594,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter> properties = new TreeMap<>(); Block block = getBlockFromType(blockType); StateDefinition blockStateList = - block.getStateDefinition(); + block.getStateDefinition(); for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { Property property = PROPERTY_CACHE.getUnchecked(state); properties.put(property.getName(), property); @@ -538,28 +603,28 @@ public final class PaperweightAdapter implements BukkitImplAdapter (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) + __ -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData) )); } @Override public void sendFakeOP(Player player) { ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 + ((CraftPlayer) player).getHandle(), (byte) 28 )); } @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { ItemStack stack = new ItemStack( - DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())), - item.getAmount() + DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().id())), + item.getAmount() ); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); return CraftItemStack.asCraftMirror(stack); @@ -569,12 +634,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); @Override public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { @@ -591,15 +656,15 @@ public final class PaperweightAdapter implements BukkitImplAdapter map = (Map) serverWorldsField.get(Bukkit.getServer()); + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); map.remove("faweregentempworld"); } catch (IllegalAccessException ignored) { } @@ -720,7 +787,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null + ftr.isDone() && Futures.getUnchecked(ftr) == null )) { return false; } @@ -735,7 +802,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter>) - getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) + ((CompletableFuture>) + getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true)) + .thenApply(either -> either.left().orElse(null)) ); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Couldn't load chunk for regen.", e); @@ -790,12 +857,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS, + SideEffect.LIGHTING, + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.EVENTS, + SideEffect.UPDATE ); @Override @@ -804,10 +871,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME); + biomeRegistry.getTagNames().forEach(tagKey -> { + String key = tagKey.location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.getTag(tagKey) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(this::adapt) + .collect(Collectors.toSet())) + ); + } + }); + } + + @Override + public void sendBiomeUpdates(World world, Iterable chunks) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); + for (BlockVector2 chunk : chunks) { + nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); + } + originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + } + // ------------------------------------------------------------------------ // Code that is less likely to break // ------------------------------------------------------------------------ @@ -827,51 +933,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLin(net.minecraft.nbt.Tag foreign) { if (foreign == null) { return null; } if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); for (String str : foreignKeys) { net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); + values.put(str, toNativeLin(base)); } - return CompoundBinaryTag.from(values); + return LinCompoundTag.of(values); } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); + return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); } else if (foreign instanceof net.minecraft.nbt.ListTag) { try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); + return toNativeLinList((net.minecraft.nbt.ListTag) foreign); } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); } } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); + return LinStringTag.of(foreign.getAsString()); } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + return LinEndTag.instance(); } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); } /** @@ -882,14 +986,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + LinListTag.Builder> builder = LinListTag.builder( + LinTagType.fromId(LinTagId.fromId(foreign.getElementType())) + ); for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); + builder.add(toNativeLin(tag)); } - return values.build(); + return builder.build(); } /** @@ -899,44 +1005,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter foreign) { if (foreign == null) { return null; } - if (foreign instanceof CompoundBinaryTag) { + if (foreign instanceof LinCompoundTag compoundTag) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); + for (var entry : compoundTag.value().entrySet()) { + tag.put(entry.getKey(), fromNativeLin(entry.getValue())); } return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag) { + } else if (foreign instanceof LinByteTag byteTag) { + return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte()); + } else if (foreign instanceof LinByteArrayTag byteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value()); + } else if (foreign instanceof LinDoubleTag doubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble()); + } else if (foreign instanceof LinFloatTag floatTag) { + return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat()); + } else if (foreign instanceof LinIntTag intTag) { + return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt()); + } else if (foreign instanceof LinIntArrayTag intArrayTag) { + return new net.minecraft.nbt.IntArrayTag(intArrayTag.value()); + } else if (foreign instanceof LinLongArrayTag longArrayTag) { + return new net.minecraft.nbt.LongArrayTag(longArrayTag.value()); + } else if (foreign instanceof LinListTag listTag) { net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - ListBinaryTag foreignList = (ListBinaryTag) foreign; - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); + for (var t : listTag.value()) { + tag.add(fromNativeLin(t)); } return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { + } else if (foreign instanceof LinLongTag longTag) { + return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong()); + } else if (foreign instanceof LinShortTag shortTag) { + return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort()); + } else if (foreign instanceof LinStringTag stringTag) { + return net.minecraft.nbt.StringTag.valueOf(stringTag.value()); + } else if (foreign instanceof LinEndTag) { return net.minecraft.nbt.EndTag.INSTANCE; } else { throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); @@ -975,7 +1080,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter. */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -35,7 +35,6 @@ import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.core.Direction; import net.minecraft.nbt.NbtOps; import net.minecraft.network.chat.Component; @@ -48,7 +47,9 @@ import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.item.DyeColor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -62,7 +63,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; -import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) @@ -76,18 +76,17 @@ import javax.annotation.Nullable; * receive the source version in the compound */ @SuppressWarnings({ "rawtypes", "unchecked" }) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { +public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - //FAWE start - BinaryTag @SuppressWarnings("unchecked") @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); + return (T) fixChunk((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); + return (T) fixBlockEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); + return (T) fixEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -98,24 +97,23 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return original; } - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); + private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); + private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); + private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - //FAWE end private String fixBlockState(String blockState, int srcVer) { net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); @@ -173,7 +171,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final int LEGACY_VERSION = 1343; private static int DATA_VERSION; - static PaperweightDataConverters INSTANCE; + public static PaperweightDataConverters INSTANCE; private final Map> converters = new EnumMap<>(LegacyType.class); private final Map> inspectors = new EnumMap<>(LegacyType.class); @@ -204,7 +202,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } } - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { + public PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { super(dataVersion); DATA_VERSION = dataVersion; INSTANCE = this; diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightFakePlayer.java similarity index 82% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightFakePlayer.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightFakePlayer.java index 87dca94f2..82caa9a92 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightFakePlayer.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightFakePlayer.java @@ -17,17 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2; import com.mojang.authlib.GameProfile; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -38,9 +40,12 @@ import java.util.UUID; class PaperweightFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false + ); PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } @Override @@ -67,7 +72,7 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void updateOptions(ServerboundClientInformationPacket packet) { + public void updateOptions(ClientInformation clientOptions) { } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java similarity index 85% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java index dc44a165a..a27f01b70 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java @@ -17,9 +17,8 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; @@ -27,17 +26,20 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; -import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; @@ -70,8 +72,8 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess { +public final class PaperweightFaweAdapter extends FaweAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; @@ -124,18 +117,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } } - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); + super(new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2.PaperweightAdapter()); + } + + public Function blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId()) + ); } @Nullable @@ -248,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BlockState getBlock(Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -268,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BaseBlock getFullBlock(final Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -288,7 +277,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); + return state.toBaseBlock((LinCompoundTag) toNativeLin(tag)); } } @@ -302,10 +291,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); + return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); } @Override @@ -319,14 +305,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements if (id != null) { EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { + Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); + final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag); + final Map> tags = NbtUtils.getLinCompoundTagValues(tag); + tags.put("Id", LinStringTag.of(id)); + return LinCompoundTag.of(tags); }; return new LazyBaseEntity(type, saveTag); } else { @@ -450,7 +436,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); + ServerLevel nmsWorld = getServerLevel(world); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); if (map != null && wasAccessibleSinceLastSave(map)) { boolean flag = false; @@ -488,8 +474,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements int internalId = BlockStateIdAccess.getBlockStateId(blockState); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) + getServerLevel(world), + new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z()) ); } @@ -497,7 +483,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { ItemStack stack = new ItemStack( DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM) - .get(ResourceLocation.tryParse(baseItemStack.getType().getId())), + .get(ResourceLocation.tryParse(baseItemStack.getType().id())), baseItemStack.getAmount() ); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); @@ -505,54 +491,33 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; + protected void preCaptureStates(final ServerLevel serverLevel) { + serverLevel.captureTreeGeneration = true; + serverLevel.captureBlockStates = true; + } + + @Override + protected List getCapturedBlockStatesCopy(final ServerLevel serverLevel) { + return new ArrayList<>(serverLevel.capturedBlockStates.values()); + } + + @Override + protected void postCaptureBlockStates(final ServerLevel serverLevel) { + serverLevel.captureBlockStates = false; + serverLevel.captureTreeGeneration = false; + serverLevel.capturedBlockStates.clear(); + } + + @Override + protected ServerLevel getServerLevel(final World world) { + return ((CraftWorld) world).getHandle(); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); + weStack.setNbt(((LinCompoundTag) toNativeLin(nmsStack.getTag()))); return weStack; } @@ -585,7 +550,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements .getServer() .registryAccess() .registryOrThrow(BIOME); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); + ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id()); Biome biome = registry.get(resourceLocation); return registry.getId(biome); } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java similarity index 92% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java index e1230b20e..352e9b958 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; @@ -9,22 +9,21 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -133,14 +132,14 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; + private final IntPair chunkPos; private final int minHeight; private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -126,8 +140,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc this.maxSectionPosition = maxHeight >> 4; this.skyLight = new DataLayer[getSectionCount()]; this.blockLight = new DataLayer[getSectionCount()]; - this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); + this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); } public int getChunkX() { @@ -144,13 +159,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + // Increment regardless of whether copy will be created or not to return null from getCopy() + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -234,23 +264,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -270,8 +301,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( LightLayer.BLOCK, sectionPos, - dataLayer, - true + dataLayer ); } skyLight[alayer] = dataLayer; @@ -298,7 +328,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc Arrays.fill(LAYER_COUNT, (byte) 15); dataLayer = new DataLayer(LAYER_COUNT); ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true + dataLayer ); } blockLight[alayer] = dataLayer; @@ -314,14 +344,22 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + public @Nullable FaweCompoundTag entity(final UUID uuid) { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -329,13 +367,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { + ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -348,10 +387,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -363,12 +402,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { + CompoundTag tag = new CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -385,12 +424,19 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - // Remove existing tiles. Create a copy so that we can remove blocks Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -462,6 +508,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -479,7 +527,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } } } else { - setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes()); + PalettedContainer> paletteBiomes = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + if (paletteBiomes != null) { + PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes); + } } } } @@ -488,7 +543,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc bitMask |= 1 << getSectionIndex; - char[] setArr = set.load(layerNo); + // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to + // this chunk GET when #updateGet is called. Future dords, please listen this time. + char[] tmp = set.load(layerNo); + char[] setArr = new char[tmp.length]; + System.arraycopy(tmp, 0, setArr, 0, tmp.length); // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // submitted to keep loaded internal chunks to queue target size. @@ -517,13 +576,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (existingSection == null) { PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, @@ -533,6 +587,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -589,16 +645,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc existingSection.getBiomes() ); - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - adapter, - biomeRegistry, - biomeData - ); + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + this::loadPrivately, + setArr, + adapter, + biomeRegistry, + biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() + ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -672,7 +729,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -684,48 +741,47 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + entity.setUUID(NbtUtils.uuid(nativeTag)); + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -740,30 +796,29 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; + final int x = blockHash.x() + bx; + final int y = blockHash.y(); + final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); @@ -779,15 +834,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified nmsChunk.mustNotSave = false; nmsChunk.setUnsaved(true); // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); + if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) { + this.send(); } if (finalizer != null) { finalizer.run(); @@ -809,7 +863,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (callback == null) { if (finalizer != null) { - finalizer.run(); + queueHandler.async(finalizer, null); } return null; } else { @@ -875,9 +929,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -885,8 +937,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send() { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); + } } /** @@ -997,9 +1051,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); @@ -1045,8 +1097,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( lightLayer, sectionPos, - dataLayer, - true + dataLayer ); } synchronized (dataLayer) { @@ -1069,38 +1120,25 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int sectionIndex, final PalettedContainerRO> data ) { - PalettedContainer> biomeData; - if (data instanceof PalettedContainer> palettedContainer) { - biomeData = palettedContainer; - } else { - LOGGER.warn( - "Cannot correctly set biomes to world, existing biomes may be lost. Expected class " + - "type {} but got {}", - PalettedContainer.class.getSimpleName(), - data.getClass().getSimpleName() - ); - biomeData = data.recreate(); - } BiomeType[] sectionBiomes; if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { - return biomeData; + return null; } + PalettedContainer> biomeData = data.recreate(); for (int y = 0, index = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { for (int x = 0; x < 4; x++, index++) { BiomeType biomeType = sectionBiomes[index]; if (biomeType == null) { - continue; + biomeData.set(x, y, z, data.get(x, y, z)); + } else { + biomeData.set( + x, + y, + z, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType)) + ); } - biomeData.set( - x, - y, - z, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)) - ); } } } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java similarity index 71% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java index 7a387a887..e655dd206 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java @@ -1,21 +1,22 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -24,8 +25,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -37,14 +41,14 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; final LevelChunk levelChunk; - private PalettedContainer>[] biomes = null; + private Holder[][] biomes = null; protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.levelChunk = levelChunk; @@ -55,44 +59,35 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId())) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -105,7 +100,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -142,7 +138,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BiomeType getBiomeType(int x, int y, int z) { - Holder biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2); + Holder biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2]; return PaperweightPlatformAdapter.adapt(biome, serverLevel); } @@ -171,10 +167,25 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { if (biomes == null) { - biomes = new PalettedContainer[getSectionCount()]; + biomes = new Holder[getSectionCount()][]; + } + if (biomes[layer] == null) { + biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - biomes[layer] = palettedContainer.copy(); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } else { LOGGER.error( "Cannot correctly save biomes to history. Expected class type {} but got {}", @@ -187,7 +198,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -199,6 +210,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } @@ -213,6 +228,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightMapChunkUtil.java similarity index 96% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightMapChunkUtil.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightMapChunkUtil.java index 7c7f39d9a..e6501086e 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightMapChunkUtil.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightMapChunkUtil.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java similarity index 89% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 8cb8a8662..d7fab2dd6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.destroystokyo.paper.util.maplist.EntityList; import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; @@ -7,8 +7,8 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -26,6 +26,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -57,8 +58,7 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R1.CraftChunk; -import sun.misc.Unsafe; +import org.bukkit.craftbukkit.v1_20_R2.CraftChunk; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -98,21 +98,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final Field fieldTickingFluidCount; private static final Field fieldTickingBlockCount; - private static final Field fieldNonEmptyBlockCount; private static final MethodHandle methodGetVisibleChunk; - private static final int CHUNKSECTION_BASE; - private static final int CHUNKSECTION_SHIFT; - private static final Field fieldThreadingDetector; - private static final long fieldThreadingDetectorOffset; - private static final Field fieldLock; - private static final long fieldLockOffset; private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodremoveTickingBlockEntity; + private static final Field fieldBiomes; /* * This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java @@ -129,6 +123,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Field LEVEL_CHUNK_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -148,8 +144,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldTickingFluidCount.setAccessible(true); fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f")); fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e")); - fieldNonEmptyBlockCount.setAccessible(true); + Field tmpFieldBiomes; + try { + // It seems to actually be biomes, but is apparently obfuscated to "i" + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes"); + } catch (NoSuchFieldException ignored) { + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i"); + } + fieldBiomes = tmpFieldBiomes; + fieldBiomes.setAccessible(true); Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( "getVisibleChunkIfPresent", @@ -158,20 +161,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { getVisibleChunkIfPresent.setAccessible(true); methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent); - Unsafe unsafe = ReflectionUtils.getUnsafe(); if (!PaperLib.isPaper()) { fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f")); - fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector); - + fieldThreadingDetector.setAccessible(true); fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c")); - fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + fieldLock.setAccessible(true); } else { // in paper, the used methods are synchronized properly fieldThreadingDetector = null; - fieldThreadingDetectorOffset = -1; - fieldLock = null; - fieldLockOffset = -1; } Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( @@ -194,12 +192,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q")); fieldRemove.setAccessible(true); - CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class); - int scale = unsafe.arrayIndexScale(LevelChunkSection[].class); - if ((scale & (scale - 1)) != 0) { - throw new Error("data type scale not a power of two"); - } - CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); boolean chunkRewrite; try { ServerLevel.class.getDeclaredMethod("getEntityLookup"); @@ -222,6 +214,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { @@ -244,16 +243,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE; - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -266,19 +263,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } try { synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); PalettedContainer blocks = section.getStates(); - ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject( - blocks, - fieldThreadingDetectorOffset - ); + ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks); synchronized (currentThreadingDetector) { - Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset); + Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector); if (currentLock instanceof DelegateSemaphore delegateSemaphore) { return delegateSemaphore; } DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock); + fieldLock.set(currentThreadingDetector, newLock); return newLock; } } @@ -355,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -376,26 +369,35 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { if (levelChunk == null) { return; } - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - ); + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } + MinecraftServer.getServer().execute(() -> { + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } @@ -425,7 +427,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @Nullable PalettedContainer> biomes ) { if (set == null) { - return newChunkSection(layer, biomeRegistry, biomes); + return newChunkSection(biomeRegistry, biomes); } final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); @@ -515,7 +517,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @SuppressWarnings("deprecation") // Only deprecated in paper private static LevelChunkSection newChunkSection( - int layer, Registry biomeRegistry, @Nullable PalettedContainer> biomes ) { @@ -530,6 +531,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { return new LevelChunkSection(dataPaletteBlocks, biomes); } + public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer> biomes) { + try { + fieldBiomes.set(section, biomes); + } catch (IllegalAccessException e) { + LOGGER.error("Could not set biomes to chunk section", e); + } + } + /** * Create a new {@link PalettedContainer}. Should only be used if no biome container existed beforehand. */ diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java similarity index 99% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java index abc8d6150..5fafdc439 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java new file mode 100644 index 000000000..b92835a82 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java @@ -0,0 +1,77 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; + +import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.util.Unit; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkStatus; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.IntConsumer; + +public class PaperweightStarlightRelighter extends StarlightRelighter { + + private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); + + public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + super(serverLevel, queue); + } + + @Override + protected ChunkPos createChunkPos(final long chunkKey) { + return new ChunkPos(chunkKey); + } + + @Override + protected long asLong(final int chunkX, final int chunkZ) { + return ChunkPos.asLong(chunkX, chunkZ); + } + + @Override + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); + } + + protected void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ) { + try { + serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); + } catch (Exception e) { + LOGGER.error("Error occurred on relighting", e); + } + } + + /* + * Allow the server to unload the chunks again. + * Also, if chunk packets are sent delayed, we need to do that here + */ + protected void postProcessChunks(Set coords) { + boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; + for (ChunkPos pos : coords) { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(new IntPair(x, z), serverLevel, x, z); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighterFactory.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighterFactory.java index 960174342..4afc48689 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighterFactory.java @@ -1,23 +1,20 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import javax.annotation.Nonnull; public class PaperweightStarlightRelighterFactory implements RelighterFactory { @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { org.bukkit.World w = Bukkit.getWorld(world.getName()); if (w == null) { return NullRelighter.INSTANCE; diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/nbt/PaperweightLazyCompoundTag.java similarity index 91% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/nbt/PaperweightLazyCompoundTag.java rename to worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/nbt/PaperweightLazyCompoundTag.java index 7db487c3f..68dbc6b8e 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/nbt/PaperweightLazyCompoundTag.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/nbt/PaperweightLazyCompoundTag.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.LazyCompoundTag; @@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.nbt.NumericTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.ArrayList; import java.util.Collections; @@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { @Override @SuppressWarnings("unchecked") - public Map getValue() { + public Map> getValue() { if (compoundTag == null) { compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); } @@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @Override - public CompoundBinaryTag asBinaryTag() { + public LinCompoundTag toLinTag() { getValue(); - return compoundTag.asBinaryTag(); + return compoundTag.toLinTag(); } public boolean containsKey(String key) { @@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key) { + public List> getList(String key) { net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); for (net.minecraft.nbt.Tag elem : nbtList) { if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { list.add(new PaperweightLazyCompoundTag(compoundTag)); @@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { + public > List getList(String key, Class listType) { ListTag listTag = getListTag(key); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java new file mode 100644 index 000000000..e892c6f7e --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java @@ -0,0 +1,303 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.regen; + +import com.fastasyncworldedit.bukkit.adapter.Regenerator; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.queue.IChunkCache; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.RegenOptions; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_20_R2.CraftServer; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.generator.BiomeProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightRegen extends Regenerator { + + private static final Field serverWorldsField; + private static final Field paperConfigField; + private static final Field generatorSettingBaseSupplierField; + + + static { + try { + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + Field tmpPaperConfigField; + try { //only present on paper + tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); + tmpPaperConfigField.setAccessible(true); + } catch (Exception e) { + tmpPaperConfigField = null; + } + paperConfigField = tmpPaperConfigField; + + generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( + "settings", "e")); + generatorSettingBaseSupplierField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //runtime + private ServerLevel originalServerWorld; + private ServerLevel freshWorld; + private LevelStorageSource.LevelStorageAccess session; + + private Path tempDir; + + public PaperweightRegen( + World originalBukkitWorld, + Region region, + Extent target, + RegenOptions options + ) { + super(originalBukkitWorld, region, target, options); + } + + @Override + protected void runTasks(final BooleanSupplier shouldKeepTicking) { + while (shouldKeepTicking.getAsBoolean()) { + if (!this.freshWorld.getChunkSource().pollTask()) { + return; + } + } + } + + @Override + protected boolean prepare() { + this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); + seed = options.getSeed().orElse(originalServerWorld.getSeed()); + return true; + } + + @Override + protected boolean initNewWorld() throws Exception { + //world folder + tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + + //prepare for world init (see upstream implementation for reference) + org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); + org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); + ResourceKey levelStemResourceKey = getWorldDimKey(environment); + session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); + PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; + + MinecraftServer server = originalServerWorld.getCraftServer().getServer(); + WorldOptions originalOpts = originalWorldData.worldGenOptions(); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + LevelSettings newWorldSettings = new LevelSettings( + "faweregentempworld", + originalWorldData.settings.gameType(), + originalWorldData.settings.hardcore(), + originalWorldData.settings.difficulty(), + originalWorldData.settings.allowCommands(), + originalWorldData.settings.gameRules(), + originalWorldData.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + originalWorldData.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : originalWorldData.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + BiomeProvider biomeProvider = getBiomeProvider(); + + + //init world + freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( + server, + server.executor, + session, + newWorldData, + originalServerWorld.dimension(), + new LevelStem( + originalServerWorld.dimensionTypeRegistration(), + originalServerWorld.getChunkSource().getGenerator() + ), + new RegenNoOpWorldLoadListener(), + originalServerWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalServerWorld.getRandomSequences(), + environment, + generator, + biomeProvider + ) { + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; + + @Override + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + if (options.hasBiomeType()) { + return singleBiome; + } + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } + }).get(); + freshWorld.noSave = true; + removeWorldFromWorldsMap(); + newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name + if (paperConfigField != null) { + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); + } + return true; + } + + @Override + protected void cleanup() { + try { + session.close(); + } catch (Exception ignored) { + } + + //shutdown chunk provider + try { + Fawe.instance().getQueueHandler().sync(() -> { + try { + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ignored) { + } + + //remove world from server + try { + Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); + } catch (Exception ignored) { + } + + //delete directory + try { + SafeFiles.tryHardToDeleteDir(tempDir); + } catch (Exception ignored) { + } + } + + @Override + protected IChunkCache initSourceQueueCache() { + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); + } + + //util + @SuppressWarnings("unchecked") + private void removeWorldFromWorldsMap() { + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { + return switch (env) { + case NETHER -> LevelStem.NETHER; + case THE_END -> LevelStem.END; + default -> LevelStem.OVERWORLD; + }; + } + + private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { + + private RegenNoOpWorldLoadListener() { + } + + @Override + public void updateSpawnPos(@NotNull ChunkPos spawnPos) { + } + + @Override + public void onStatusChange( + final @NotNull ChunkPos pos, + @org.jetbrains.annotations.Nullable final ChunkStatus status + ) { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + } + + // TODO Paper only(?) @Override + public void setChunkRadius(int radius) { + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts similarity index 64% rename from worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts rename to worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts index f7f40ce66..be348efdb 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts @@ -11,7 +11,7 @@ repositories { } dependencies { - // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ - the().paperDevBundle("1.18.2-R0.1-20220920.010157-167") + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT + the().paperDevBundle("1.20.4-R0.1-20241030.192207-176") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java similarity index 69% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java index 428176c5f..ded4bcfdd 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java @@ -17,17 +17,17 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTConstants; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -55,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeCategory; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; @@ -82,6 +69,8 @@ import com.sk89q.worldedit.world.item.ItemType; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; @@ -93,6 +82,7 @@ import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.RandomSource; import net.minecraft.util.StringRepresentable; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Clearable; @@ -123,21 +113,39 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.generator.ChunkGenerator; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinEndTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -145,6 +153,7 @@ import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -159,20 +168,21 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public final class PaperweightAdapter implements BukkitImplAdapter { - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); private final Field serverWorldsField; private final Method getChunkFutureMethod; private final Field chunkProviderExecutorField; private final Watchdog watchdog; + private static final RandomSource random = RandomSource.create(); + // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ @@ -182,21 +192,21 @@ public final class PaperweightAdapter implements BukkitImplAdapter> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - int internalId = Block.getId(blockData); - BlockState state = BlockStateIdAccess.getBlockStateById(internalId); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; + return adapt(blockData); } @Override @@ -346,21 +371,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter> biomeTypeToNMSCache = new HashMap<>(); private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); - /* @Override + @Override public BiomeType getBiome(Location location) { checkNotNull(location); @@ -387,14 +407,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter> 4, z >> 4); - chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.getId()))))); + chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id()))))); chunk.setUnsaved(true); - }*/ + } @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1.PaperweightWorldNativeAccess(this, - new WeakReference<>(((CraftWorld) world).getHandle())); + public WorldNativeAccess createWorldNativeAccess(World world) { + return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } private static net.minecraft.core.Direction adapt(Direction face) { @@ -417,13 +436,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states + StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, + Map, Object> states ) { for (Map.Entry, Object> state : states.entrySet()) { net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); + stateContainer.getProperty(state.getKey().getName()); Comparable value = (Comparable) state.getValue(); // we may need to adapt this value, depending on the source prop if (property instanceof DirectionProperty) { @@ -432,16 +451,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); + .getValue(enumName).orElseThrow(() -> + new IllegalStateException( + "Enum property " + property.getName() + " does not contain " + enumName + ) + ); } newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value + (net.minecraft.world.level.block.state.properties.Property) property, + (Comparable) value ); } return newState; @@ -465,7 +484,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter (CompoundBinaryTag) toNativeBinary(tag)) + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)) ); } @@ -478,12 +497,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); + private static final LoadingCache> PROPERTY_CACHE = CacheBuilder + .newBuilder() + .build(new CacheLoader<>() { + @Override + public Property load(net.minecraft.world.level.block.state.properties.Property state) { + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + return new DirectionalProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> Direction.valueOf(((StringRepresentable) e) + .getSerializedName() + .toUpperCase(Locale.ROOT))) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + return new EnumProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> ((StringRepresentable) e).getSerializedName()) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state + .getClass() + .getSimpleName()); + } + } + }); @SuppressWarnings({ "rawtypes" }) @Override @@ -556,7 +593,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter> properties = new TreeMap<>(); Block block = getBlockFromType(blockType); StateDefinition blockStateList = - block.getStateDefinition(); + block.getStateDefinition(); for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { Property property = PROPERTY_CACHE.getUnchecked(state); properties.put(property.getName(), property); @@ -565,39 +602,28 @@ public final class PaperweightAdapter implements BukkitImplAdapter (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) + __ -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData) )); } - /*@Override - public void sendFakeNBT(Player player, BlockVector3 pos, CompoundTag nbtData) { - ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create( - new StructureBlockEntity( - new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - Blocks.STRUCTURE_BLOCK.defaultBlockState() - ), - __ -> (net.minecraft.nbt.CompoundTag) fromNative(nbtData) - )); - }*/ - @Override public void sendFakeOP(Player player) { ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 + ((CraftPlayer) player).getHandle(), (byte) 28 )); } @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { ItemStack stack = new ItemStack( - DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())), - item.getAmount() + DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().id())), + item.getAmount() ); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); return CraftItemStack.asCraftMirror(stack); @@ -607,7 +633,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter map = (Map) serverWorldsField.get(Bukkit.getServer()); + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); map.remove("faweregentempworld"); } catch (IllegalAccessException ignored) { } @@ -759,7 +786,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null + ftr.isDone() && Futures.getUnchecked(ftr) == null )) { return false; } @@ -774,7 +801,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter>) - getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) + ((CompletableFuture>) + getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true)) + .thenApply(either -> either.left().orElse(null)) ); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Couldn't load chunk for regen.", e); @@ -829,12 +856,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS, + SideEffect.LIGHTING, + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.EVENTS, + SideEffect.UPDATE ); @Override @@ -843,10 +870,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME); + biomeRegistry.getTagNames().forEach(tagKey -> { + String key = tagKey.location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.getTag(tagKey) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(this::adapt) + .collect(Collectors.toSet())) + ); + } + }); + } + + @Override + public void sendBiomeUpdates(World world, Iterable chunks) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); + for (BlockVector2 chunk : chunks) { + nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); + } + originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + } // ------------------------------------------------------------------------ // Code that is less likely to break @@ -877,51 +932,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLin(net.minecraft.nbt.Tag foreign) { if (foreign == null) { return null; } if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); for (String str : foreignKeys) { net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); + values.put(str, toNativeLin(base)); } - return CompoundBinaryTag.from(values); + return LinCompoundTag.of(values); } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); + return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); } else if (foreign instanceof net.minecraft.nbt.ListTag) { try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); + return toNativeLinList((net.minecraft.nbt.ListTag) foreign); } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); } } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); + return LinStringTag.of(foreign.getAsString()); } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + return LinEndTag.instance(); } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); } /** @@ -932,14 +985,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + LinListTag.Builder> builder = LinListTag.builder( + LinTagType.fromId(LinTagId.fromId(foreign.getElementType())) + ); for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); + builder.add(toNativeLin(tag)); } - return values.build(); + return builder.build(); } /** @@ -949,44 +1004,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter foreign) { if (foreign == null) { return null; } - if (foreign instanceof CompoundBinaryTag) { + if (foreign instanceof LinCompoundTag compoundTag) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); + for (var entry : compoundTag.value().entrySet()) { + tag.put(entry.getKey(), fromNativeLin(entry.getValue())); } return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag) { + } else if (foreign instanceof LinByteTag byteTag) { + return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte()); + } else if (foreign instanceof LinByteArrayTag byteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value()); + } else if (foreign instanceof LinDoubleTag doubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble()); + } else if (foreign instanceof LinFloatTag floatTag) { + return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat()); + } else if (foreign instanceof LinIntTag intTag) { + return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt()); + } else if (foreign instanceof LinIntArrayTag intArrayTag) { + return new net.minecraft.nbt.IntArrayTag(intArrayTag.value()); + } else if (foreign instanceof LinLongArrayTag longArrayTag) { + return new net.minecraft.nbt.LongArrayTag(longArrayTag.value()); + } else if (foreign instanceof LinListTag listTag) { net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - ListBinaryTag foreignList = (ListBinaryTag) foreign; - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); + for (var t : listTag.value()) { + tag.add(fromNativeLin(t)); } return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { + } else if (foreign instanceof LinLongTag longTag) { + return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong()); + } else if (foreign instanceof LinShortTag shortTag) { + return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort()); + } else if (foreign instanceof LinStringTag stringTag) { + return net.minecraft.nbt.StringTag.valueOf(stringTag.value()); + } else if (foreign instanceof LinEndTag) { return net.minecraft.nbt.EndTag.INSTANCE; } else { throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); @@ -1025,7 +1079,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter. */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -35,7 +35,6 @@ import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.core.Direction; import net.minecraft.nbt.NbtOps; import net.minecraft.network.chat.Component; @@ -48,7 +47,9 @@ import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.item.DyeColor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -62,7 +63,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; -import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) @@ -76,18 +76,17 @@ import javax.annotation.Nullable; * receive the source version in the compound */ @SuppressWarnings({ "rawtypes", "unchecked" }) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { +public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - //FAWE start - BinaryTag @SuppressWarnings("unchecked") @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); + return (T) fixChunk((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); + return (T) fixBlockEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); + return (T) fixEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -98,24 +97,23 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return original; } - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); + private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); + private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); + private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - //FAWE end private String fixBlockState(String blockState, int srcVer) { net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); @@ -173,7 +171,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final int LEGACY_VERSION = 1343; private static int DATA_VERSION; - static PaperweightDataConverters INSTANCE; + public static PaperweightDataConverters INSTANCE; private final Map> converters = new EnumMap<>(LegacyType.class); private final Map> inspectors = new EnumMap<>(LegacyType.class); @@ -204,7 +202,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } } - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { + public PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { super(dataVersion); DATA_VERSION = dataVersion; INSTANCE = this; @@ -234,7 +232,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } @Override - public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); if (sourceVer < LEGACY_VERSION && legacyType != null) { diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightFakePlayer.java similarity index 80% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightFakePlayer.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightFakePlayer.java index ee7d82f09..83520e453 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightFakePlayer.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightFakePlayer.java @@ -17,17 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3; import com.mojang.authlib.GameProfile; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -38,9 +40,12 @@ import java.util.UUID; class PaperweightFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false + ); PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } @Override @@ -67,7 +72,7 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void updateOptions(ServerboundClientInformationPacket packet) { + public void updateOptions(ClientInformation clientOptions) { } @Override @@ -88,6 +93,6 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void openTextEdit(SignBlockEntity sign) { + public void openTextEdit(SignBlockEntity sign, boolean front) { } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java similarity index 83% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java index 22d9f917b..1f51c66ca 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java @@ -17,27 +17,30 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3; +import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; -import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; @@ -70,8 +73,8 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess EmptyBlockGetter + return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); } @Override @@ -126,12 +112,12 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; + return blockState.getPistonPushReaction() == PushReaction.DESTROY; } @Override public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; + return blockState.getPistonPushReaction() == PushReaction.BLOCK; } @Override @@ -139,14 +125,15 @@ public class PaperweightBlockMaterial implements BlockMaterial { return block.isRandomlyTicking(blockState); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return material.isSolid(); + return blockState.blocksMotion(); } @Override public boolean isBurnable() { - return material.isFlammable(); + return craftMaterial.isBurnable(); } @Override @@ -157,12 +144,12 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); + return blockState.canBeReplaced(); } @Override public boolean isTranslucent() { - return isTranslucent; + return !blockState.canOcclude(); } @Override @@ -176,14 +163,14 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } @Override public int getMapColor() { // rgb field - return material.getColor().col; + return block.defaultMapColor().col; } } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java similarity index 81% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java index 33c209632..1abfc5b04 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java @@ -1,28 +1,24 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter; +import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.NbtUtils; -import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.regen.PaperweightRegen; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.regen.PaperweightRegen; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -38,11 +34,7 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -77,19 +69,20 @@ import net.minecraft.world.level.chunk.LevelChunk; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.TreeType; +import org.bukkit.World; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState; -import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_20_R1.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey; import org.bukkit.entity.Player; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -105,14 +98,14 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import static net.minecraft.core.registries.Registries.BIOME; -public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements - IDelegateBukkitImplAdapter { +public final class PaperweightFaweAdapter extends FaweAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; @@ -124,18 +117,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } } - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); + super(new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter()); + } + + public Function blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId()) + ); } @Nullable @@ -248,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BlockState getBlock(Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -268,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BaseBlock getFullBlock(final Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -288,7 +277,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); + return state.toBaseBlock((LinCompoundTag) toNativeLin(tag)); } } @@ -302,10 +291,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); + return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); } @Override @@ -319,14 +305,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements if (id != null) { EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { + Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); + final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag); + final Map> tags = NbtUtils.getLinCompoundTagValues(tag); + tags.put("Id", LinStringTag.of(id)); + return LinCompoundTag.of(tags); }; return new LazyBaseEntity(type, saveTag); } else { @@ -450,7 +436,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); + ServerLevel nmsWorld = getServerLevel(world); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); if (map != null && wasAccessibleSinceLastSave(map)) { boolean flag = false; @@ -488,8 +474,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements int internalId = BlockStateIdAccess.getBlockStateId(blockState); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) + getServerLevel(world), + new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z()) ); } @@ -497,7 +483,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { ItemStack stack = new ItemStack( DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM) - .get(ResourceLocation.tryParse(baseItemStack.getType().getId())), + .get(ResourceLocation.tryParse(baseItemStack.getType().id())), baseItemStack.getAmount() ); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); @@ -505,54 +491,33 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; + protected void preCaptureStates(final ServerLevel serverLevel) { + serverLevel.captureTreeGeneration = true; + serverLevel.captureBlockStates = true; + } + + @Override + protected List getCapturedBlockStatesCopy(final ServerLevel serverLevel) { + return new ArrayList<>(serverLevel.capturedBlockStates.values()); + } + + @Override + protected void postCaptureBlockStates(final ServerLevel serverLevel) { + serverLevel.captureBlockStates = false; + serverLevel.captureTreeGeneration = false; + serverLevel.capturedBlockStates.clear(); + } + + @Override + protected ServerLevel getServerLevel(final World world) { + return ((CraftWorld) world).getHandle(); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); + weStack.setNbt(((LinCompoundTag) toNativeLin(nmsStack.getTag()))); return weStack; } @@ -585,7 +550,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements .getServer() .registryAccess() .registryOrThrow(BIOME); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); + ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id()); Biome biome = registry.get(resourceLocation); return registry.getId(biome); } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java similarity index 91% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java index dbe0150a9..4fb3e0485 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; @@ -9,21 +9,21 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -132,14 +132,14 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; + private final IntPair chunkPos; private final int minHeight; private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -130,6 +142,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc this.blockLight = new DataLayer[getSectionCount()]; this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); } public int getChunkX() { @@ -146,13 +159,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + // Increment regardless of whether copy will be created or not to return null from getCopy() + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -236,23 +264,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -272,8 +301,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( LightLayer.BLOCK, sectionPos, - dataLayer, - true + dataLayer ); } skyLight[alayer] = dataLayer; @@ -300,7 +328,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc Arrays.fill(LAYER_COUNT, (byte) 15); dataLayer = new DataLayer(LAYER_COUNT); ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true + dataLayer ); } blockLight[alayer] = dataLayer; @@ -316,14 +344,22 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + public @Nullable FaweCompoundTag entity(final UUID uuid) { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -331,14 +367,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -351,10 +387,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -366,12 +402,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -388,12 +424,19 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - // Remove existing tiles. Create a copy so that we can remove blocks Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -465,6 +508,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -482,7 +527,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } } } else { - setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes()); + PalettedContainer> paletteBiomes = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + if (paletteBiomes != null) { + PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes); + } } } } @@ -524,13 +576,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (existingSection == null) { PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, @@ -540,6 +587,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -596,16 +645,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc existingSection.getBiomes() ); - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - adapter, - biomeRegistry, - biomeData - ); + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + this::loadPrivately, + setArr, + adapter, + biomeRegistry, + biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() + ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -679,7 +729,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -691,48 +741,47 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + entity.setUUID(NbtUtils.uuid(nativeTag)); + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -747,30 +796,29 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; + final int x = blockHash.x() + bx; + final int y = blockHash.y(); + final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); @@ -786,15 +834,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified nmsChunk.mustNotSave = false; nmsChunk.setUnsaved(true); // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); + if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) { + this.send(); } if (finalizer != null) { finalizer.run(); @@ -816,7 +863,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (callback == null) { if (finalizer != null) { - finalizer.run(); + queueHandler.async(finalizer, null); } return null; } else { @@ -882,9 +929,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -892,8 +937,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send() { + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); } /** @@ -1004,9 +1049,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); @@ -1052,8 +1095,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( lightLayer, sectionPos, - dataLayer, - true + dataLayer ); } synchronized (dataLayer) { @@ -1076,38 +1118,25 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int sectionIndex, final PalettedContainerRO> data ) { - PalettedContainer> biomeData; - if (data instanceof PalettedContainer> palettedContainer) { - biomeData = palettedContainer; - } else { - LOGGER.warn( - "Cannot correctly set biomes to world, existing biomes may be lost. Expected class " + - "type {} but got {}", - PalettedContainer.class.getSimpleName(), - data.getClass().getSimpleName() - ); - biomeData = data.recreate(); - } BiomeType[] sectionBiomes; if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { - return biomeData; + return null; } + PalettedContainer> biomeData = data.recreate(); for (int y = 0, index = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { for (int x = 0; x < 4; x++, index++) { BiomeType biomeType = sectionBiomes[index]; if (biomeType == null) { - continue; + biomeData.set(x, y, z, data.get(x, y, z)); + } else { + biomeData.set( + x, + y, + z, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType)) + ); } - biomeData.set( - x, - y, - z, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)) - ); } } } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java similarity index 71% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks_Copy.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java index c0b69ac80..1163c2d33 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java @@ -1,21 +1,22 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -24,8 +25,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -37,14 +41,14 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; final LevelChunk levelChunk; - private PalettedContainer>[] biomes = null; + private Holder[][] biomes = null; protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.levelChunk = levelChunk; @@ -55,44 +59,35 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId())) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -105,7 +100,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -142,7 +138,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BiomeType getBiomeType(int x, int y, int z) { - Holder biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2); + Holder biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2]; return PaperweightPlatformAdapter.adapt(biome, serverLevel); } @@ -171,10 +167,25 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { if (biomes == null) { - biomes = new PalettedContainer[getSectionCount()]; + biomes = new Holder[getSectionCount()][]; + } + if (biomes[layer] == null) { + biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - biomes[layer] = palettedContainer.copy(); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } else { LOGGER.error( "Cannot correctly save biomes to history. Expected class type {} but got {}", @@ -187,7 +198,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -199,6 +210,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } @@ -213,6 +228,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightMapChunkUtil.java similarity index 96% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightMapChunkUtil.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightMapChunkUtil.java index c8acc3cd2..97eecfc56 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightMapChunkUtil.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightMapChunkUtil.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java similarity index 84% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index d351bbacd..2c05d7466 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.destroystokyo.paper.util.maplist.EntityList; import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; @@ -7,8 +7,8 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -26,6 +26,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -44,6 +45,7 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.GlobalPalette; import net.minecraft.world.level.chunk.HashMapPalette; @@ -56,13 +58,13 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R3.CraftChunk; -import sun.misc.Unsafe; +import org.bukkit.craftbukkit.v1_20_R3.CraftChunk; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -82,6 +84,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Function; +import static java.lang.invoke.MethodType.methodType; import static net.minecraft.core.registries.Registries.BIOME; public final class PaperweightPlatformAdapter extends NMSAdapter { @@ -95,22 +98,22 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final Field fieldTickingFluidCount; private static final Field fieldTickingBlockCount; - private static final Field fieldNonEmptyBlockCount; + private static final Field fieldBiomes; private static final MethodHandle methodGetVisibleChunk; - private static final int CHUNKSECTION_BASE; - private static final int CHUNKSECTION_SHIFT; - private static final Field fieldThreadingDetector; - private static final long fieldThreadingDetectorOffset; - private static final Field fieldLock; - private static final long fieldLockOffset; private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodremoveTickingBlockEntity; + /* + * This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java + * and is only needed to support 1.19.4 versions before *and* after this change. + */ + private static final MethodHandle CRAFT_CHUNK_GET_HANDLE; + private static final Field fieldRemove; private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -120,6 +123,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Field LEVEL_CHUNK_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -135,12 +140,19 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c")); fieldPalette.setAccessible(true); - fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h")); + fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "g")); fieldTickingFluidCount.setAccessible(true); - fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g")); + fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f")); fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f")); - fieldNonEmptyBlockCount.setAccessible(true); + Field tmpFieldBiomes; + try { + // It seems to actually be biomes, but is apparently obfuscated to "i" + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes"); + } catch (NoSuchFieldException ignored) { + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i"); + } + fieldBiomes = tmpFieldBiomes; + fieldBiomes.setAccessible(true); Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( "getVisibleChunkIfPresent", @@ -149,20 +161,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { getVisibleChunkIfPresent.setAccessible(true); methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent); - Unsafe unsafe = ReflectionUtils.getUnsafe(); if (!PaperLib.isPaper()) { fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f")); - fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector); - + fieldThreadingDetector.setAccessible(true); fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c")); - fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + fieldLock.setAccessible(true); } else { // in paper, the used methods are synchronized properly fieldThreadingDetector = null; - fieldThreadingDetectorOffset = -1; - fieldLock = null; - fieldLockOffset = -1; } Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( @@ -185,12 +192,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q")); fieldRemove.setAccessible(true); - CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class); - int scale = unsafe.arrayIndexScale(LevelChunkSection[].class); - if ((scale & (scale - 1)) != 0) { - throw new Error("data type scale not a power of two"); - } - CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); boolean chunkRewrite; try { ServerLevel.class.getDeclaredMethod("getEntityLookup"); @@ -208,29 +209,48 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } try { // Non-Paper - SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "L")); + SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M")); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true); } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } + MethodHandle craftChunkGetHandle; + final MethodType type = methodType(LevelChunk.class); + try { + craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", type); + } catch (NoSuchMethodException | IllegalAccessException e) { + try { + final MethodType newType = methodType(ChunkAccess.class, ChunkStatus.class); + craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", newType); + craftChunkGetHandle = MethodHandles.insertArguments(craftChunkGetHandle, 1, ChunkStatus.FULL); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + CRAFT_CHUNK_GET_HANDLE = craftChunkGetHandle; } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE; - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -243,19 +263,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } try { synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); PalettedContainer blocks = section.getStates(); - ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject( - blocks, - fieldThreadingDetectorOffset - ); + ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks); synchronized (currentThreadingDetector) { - Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset); + Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector); if (currentLock instanceof DelegateSemaphore delegateSemaphore) { return delegateSemaphore; } DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock); + fieldLock.set(currentThreadingDetector, newLock); return newLock; } } @@ -307,7 +323,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } } addTicket(serverLevel, chunkX, chunkZ); - return (LevelChunk) chunk.getHandle(ChunkStatus.FULL); + return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); } catch (Throwable e) { e.printStackTrace(); } @@ -332,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -353,28 +369,35 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { if (levelChunk == null) { return; } - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true - ); + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } + MinecraftServer.getServer().execute(() -> { + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } @@ -404,7 +427,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @Nullable PalettedContainer> biomes ) { if (set == null) { - return newChunkSection(layer, biomeRegistry, biomes); + return newChunkSection(biomeRegistry, biomes); } final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); @@ -477,12 +500,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { .getBukkitImplAdapter() .getInternalBiomeId( BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); } - return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); + return new LevelChunkSection(blockStatePalettedContainer, biomes); } catch (final Throwable e) { throw e; } finally { @@ -495,20 +517,26 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @SuppressWarnings("deprecation") // Only deprecated in paper private static LevelChunkSection newChunkSection( - int layer, Registry biomeRegistry, @Nullable PalettedContainer> biomes ) { if (biomes == null) { - return new LevelChunkSection(layer, biomeRegistry); + return new LevelChunkSection(biomeRegistry); } PalettedContainer dataPaletteBlocks = new PalettedContainer<>( Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), - PalettedContainer.Strategy.SECTION_STATES, - null + PalettedContainer.Strategy.SECTION_STATES ); - return new LevelChunkSection(layer, dataPaletteBlocks, biomes); + return new LevelChunkSection(dataPaletteBlocks, biomes); + } + + public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer> biomes) { + try { + fieldBiomes.set(section, biomes); + } catch (IllegalAccessException e) { + LOGGER.error("Could not set biomes to chunk section", e); + } } /** @@ -545,8 +573,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { PalettedContainer> biomePalettedContainer = new PalettedContainer<>( biomeRegistry, biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); final Palette> biomePalette; diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java similarity index 99% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPostProcessor.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java index ac10f2c0a..cfd9e2753 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java new file mode 100644 index 000000000..a1ce327f9 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java @@ -0,0 +1,77 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; + +import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.util.Unit; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkStatus; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.IntConsumer; + +public class PaperweightStarlightRelighter extends StarlightRelighter { + + private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); + + public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + super(serverLevel, queue); + } + + @Override + protected ChunkPos createChunkPos(final long chunkKey) { + return new ChunkPos(chunkKey); + } + + @Override + protected long asLong(final int chunkX, final int chunkZ) { + return ChunkPos.asLong(chunkX, chunkZ); + } + + @Override + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); + } + + protected void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ) { + try { + serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); + } catch (Exception e) { + LOGGER.error("Error occurred on relighting", e); + } + } + + /* + * Allow the server to unload the chunks again. + * Also, if chunk packets are sent delayed, we need to do that here + */ + protected void postProcessChunks(Set coords) { + boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; + for (ChunkPos pos : coords) { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(new IntPair(x, z), serverLevel, x, z); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighterFactory.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighterFactory.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighterFactory.java index 3741b552c..bf9a4e8df 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightStarlightRelighterFactory.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighterFactory.java @@ -1,23 +1,20 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import javax.annotation.Nonnull; public class PaperweightStarlightRelighterFactory implements RelighterFactory { @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { org.bukkit.World w = Bukkit.getWorld(world.getName()); if (w == null) { return NullRelighter.INSTANCE; diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/nbt/PaperweightLazyCompoundTag.java similarity index 91% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/nbt/PaperweightLazyCompoundTag.java rename to worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/nbt/PaperweightLazyCompoundTag.java index ff9b73642..1d27f17a7 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/nbt/PaperweightLazyCompoundTag.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/nbt/PaperweightLazyCompoundTag.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.LazyCompoundTag; @@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.nbt.NumericTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.ArrayList; import java.util.Collections; @@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { @Override @SuppressWarnings("unchecked") - public Map getValue() { + public Map> getValue() { if (compoundTag == null) { compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); } @@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @Override - public CompoundBinaryTag asBinaryTag() { + public LinCompoundTag toLinTag() { getValue(); - return compoundTag.asBinaryTag(); + return compoundTag.toLinTag(); } public boolean containsKey(String key) { @@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key) { + public List> getList(String key) { net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); for (net.minecraft.nbt.Tag elem : nbtList) { if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { list.add(new PaperweightLazyCompoundTag(compoundTag)); @@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { + public > List getList(String key, Class listType) { ListTag listTag = getListTag(key); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java new file mode 100644 index 000000000..cce14ee1c --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java @@ -0,0 +1,303 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.regen; + +import com.fastasyncworldedit.bukkit.adapter.Regenerator; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.queue.IChunkCache; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.RegenOptions; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.generator.BiomeProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightRegen extends Regenerator { + + private static final Field serverWorldsField; + private static final Field paperConfigField; + private static final Field generatorSettingBaseSupplierField; + + + static { + try { + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + Field tmpPaperConfigField; + try { //only present on paper + tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); + tmpPaperConfigField.setAccessible(true); + } catch (Exception e) { + tmpPaperConfigField = null; + } + paperConfigField = tmpPaperConfigField; + + generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( + "settings", "e")); + generatorSettingBaseSupplierField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //runtime + private ServerLevel originalServerWorld; + private ServerLevel freshWorld; + private LevelStorageSource.LevelStorageAccess session; + + private Path tempDir; + + public PaperweightRegen( + World originalBukkitWorld, + Region region, + Extent target, + RegenOptions options + ) { + super(originalBukkitWorld, region, target, options); + } + + @Override + protected void runTasks(final BooleanSupplier shouldKeepTicking) { + while (shouldKeepTicking.getAsBoolean()) { + if (!this.freshWorld.getChunkSource().pollTask()) { + return; + } + } + } + + @Override + protected boolean prepare() { + this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); + seed = options.getSeed().orElse(originalServerWorld.getSeed()); + return true; + } + + @Override + protected boolean initNewWorld() throws Exception { + //world folder + tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + + //prepare for world init (see upstream implementation for reference) + org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); + org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); + ResourceKey levelStemResourceKey = getWorldDimKey(environment); + session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); + PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; + + MinecraftServer server = originalServerWorld.getCraftServer().getServer(); + WorldOptions originalOpts = originalWorldData.worldGenOptions(); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + LevelSettings newWorldSettings = new LevelSettings( + "faweregentempworld", + originalWorldData.settings.gameType(), + originalWorldData.settings.hardcore(), + originalWorldData.settings.difficulty(), + originalWorldData.settings.allowCommands(), + originalWorldData.settings.gameRules(), + originalWorldData.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + originalWorldData.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : originalWorldData.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + BiomeProvider biomeProvider = getBiomeProvider(); + + + //init world + freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( + server, + server.executor, + session, + newWorldData, + originalServerWorld.dimension(), + new LevelStem( + originalServerWorld.dimensionTypeRegistration(), + originalServerWorld.getChunkSource().getGenerator() + ), + new RegenNoOpWorldLoadListener(), + originalServerWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalServerWorld.getRandomSequences(), + environment, + generator, + biomeProvider + ) { + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; + + @Override + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + if (options.hasBiomeType()) { + return singleBiome; + } + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } + }).get(); + freshWorld.noSave = true; + removeWorldFromWorldsMap(); + newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name + if (paperConfigField != null) { + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); + } + return true; + } + + @Override + protected void cleanup() { + try { + session.close(); + } catch (Exception ignored) { + } + + //shutdown chunk provider + try { + Fawe.instance().getQueueHandler().sync(() -> { + try { + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ignored) { + } + + //remove world from server + try { + Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); + } catch (Exception ignored) { + } + + //delete directory + try { + SafeFiles.tryHardToDeleteDir(tempDir); + } catch (Exception ignored) { + } + } + + @Override + protected IChunkCache initSourceQueueCache() { + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); + } + + //util + @SuppressWarnings("unchecked") + private void removeWorldFromWorldsMap() { + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { + return switch (env) { + case NETHER -> LevelStem.NETHER; + case THE_END -> LevelStem.END; + default -> LevelStem.OVERWORLD; + }; + } + + private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { + + private RegenNoOpWorldLoadListener() { + } + + @Override + public void updateSpawnPos(@NotNull ChunkPos spawnPos) { + } + + @Override + public void onStatusChange( + final @NotNull ChunkPos pos, + @org.jetbrains.annotations.Nullable final ChunkStatus status + ) { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + } + + // TODO Paper only(?) @Override + public void setChunkRadius(int radius) { + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts similarity index 64% rename from worldedit-bukkit/adapters/adapter-1_19_3/build.gradle.kts rename to worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts index 6306d7cf3..ffe10e3ff 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts @@ -11,7 +11,7 @@ repositories { } dependencies { - // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ - the().paperDevBundle("1.19.3-R0.1-20230312.180621-141") + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ + the().paperDevBundle("1.20.6-R0.1-20241030.191541-126") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java similarity index 61% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java index e106c7d56..206ade66a 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java @@ -17,17 +17,17 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; -import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; import com.mojang.serialization.Lifecycle; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTConstants; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -55,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeCategory; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; @@ -81,17 +68,25 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.item.ItemType; import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.RandomSource; import net.minecraft.util.StringRepresentable; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Clearable; @@ -112,8 +107,8 @@ import net.minecraft.world.level.block.entity.StructureBlockEntity; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.LevelStorageSource; @@ -122,21 +117,39 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_19_R3.CraftServer; -import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.generator.ChunkGenerator; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinEndTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -144,6 +157,7 @@ import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -158,20 +172,25 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public final class PaperweightAdapter implements BukkitImplAdapter { - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); private final Field serverWorldsField; private final Method getChunkFutureMethod; private final Field chunkProviderExecutorField; private final Watchdog watchdog; + private static final RandomSource random = RandomSource.create(); + // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ @@ -181,21 +200,21 @@ public final class PaperweightAdapter implements BukkitImplAdapter> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - int internalId = Block.getId(blockData); - BlockState state = BlockStateIdAccess.getBlockStateById(internalId); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; + return adapt(blockData); } @Override @@ -344,17 +378,50 @@ public final class PaperweightAdapter implements BukkitImplAdapter> biomeTypeToNMSCache = new HashMap<>(); + private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); + @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightWorldNativeAccess(this, - new WeakReference<>(((CraftWorld) world).getHandle())); + public BiomeType getBiome(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + + return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString())); + } + + @Override + public void setBiome(Location location, BiomeType biome) { + checkNotNull(location); + checkNotNull(biome); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id()))))); + chunk.setUnsaved(true); + } + + @Override + public WorldNativeAccess createWorldNativeAccess(World world) { + return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } private static net.minecraft.core.Direction adapt(Direction face) { @@ -377,13 +444,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states + StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, + Map, Object> states ) { for (Map.Entry, Object> state : states.entrySet()) { net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); + stateContainer.getProperty(state.getKey().getName()); Comparable value = (Comparable) state.getValue(); // we may need to adapt this value, depending on the source prop if (property instanceof DirectionProperty) { @@ -392,16 +459,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); + .getValue(enumName).orElseThrow(() -> + new IllegalStateException( + "Enum property " + property.getName() + " does not contain " + enumName + ) + ); } newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value + (net.minecraft.world.level.block.state.properties.Property) property, + (Comparable) value ); } return newState; @@ -425,7 +492,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter (CompoundBinaryTag) toNativeBinary(tag)) + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)) ); } @@ -438,12 +505,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final LoadingCache> PROPERTY_CACHE = CacheBuilder + .newBuilder() + .build(new CacheLoader<>() { + @Override + public Property load(net.minecraft.world.level.block.state.properties.Property state) { + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + return new DirectionalProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> Direction.valueOf(((StringRepresentable) e) + .getSerializedName() + .toUpperCase(Locale.ROOT))) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + return new EnumProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> ((StringRepresentable) e).getSerializedName()) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state + .getClass() + .getSimpleName()); + } + } + }); @SuppressWarnings({ "rawtypes" }) @Override @@ -516,7 +601,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter> properties = new TreeMap<>(); Block block = getBlockFromType(blockType); StateDefinition blockStateList = - block.getStateDefinition(); + block.getStateDefinition(); for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { Property property = PROPERTY_CACHE.getUnchecked(state); properties.put(property.getName(), property); @@ -525,51 +610,67 @@ public final class PaperweightAdapter implements BukkitImplAdapter (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) + structureBlock, + (blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData) )); } @Override public void sendFakeOP(Player player) { ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 + ((CraftPlayer) player).getHandle(), (byte) 28 )); } @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { + public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); ItemStack stack = new ItemStack( - DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())), - item.getAmount() + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())), + baseItemStack.getAmount() ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()); + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); return CraftItemStack.asCraftMirror(stack); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + var registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; + CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), + itemStack.getAmount() + ); } private final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); @Override - public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { + public boolean simulateItemUse(World world, BlockVector3 position, BaseItem item, Direction face) { CraftWorld craftWorld = (CraftWorld) world; ServerLevel worldServer = craftWorld.getHandle(); - ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack - ? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); - stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); + ItemStack stack = CraftItemStack.asNMSCopy(adapt( + item instanceof BaseItemStack + ? ((BaseItemStack) item) + : new BaseItemStack(item.getType(), item.getNbtReference(), 1) + )); PaperweightFakePlayer fakePlayer; try { @@ -578,17 +679,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter map = (Map) serverWorldsField.get(Bukkit.getServer()); + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); map.remove("faweregentempworld"); } catch (IllegalAccessException ignored) { } @@ -707,7 +810,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null + ftr.isDone() && Futures.getUnchecked(ftr) == null )) { return false; } @@ -722,7 +825,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter>) - getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) + ((CompletableFuture>) + getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true)) + .thenApply(either -> either.orElse(null)) ); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Couldn't load chunk for regen.", e); @@ -777,12 +880,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS, + SideEffect.LIGHTING, + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.EVENTS, + SideEffect.UPDATE ); @Override @@ -791,10 +894,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME); + biomeRegistry.getTagNames().forEach(tagKey -> { + String key = tagKey.location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.getTag(tagKey) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(this::adapt) + .collect(Collectors.toSet())) + ); + } + }); + } + + @Override + public void sendBiomeUpdates(World world, Iterable chunks) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); + for (BlockVector2 chunk : chunks) { + nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); + } + originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + } + // ------------------------------------------------------------------------ // Code that is less likely to break // ------------------------------------------------------------------------ @@ -814,51 +956,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLin(net.minecraft.nbt.Tag foreign) { if (foreign == null) { return null; } if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); for (String str : foreignKeys) { net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); + values.put(str, toNativeLin(base)); } - return CompoundBinaryTag.from(values); + return LinCompoundTag.of(values); } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); + return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); } else if (foreign instanceof net.minecraft.nbt.ListTag) { try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); + return toNativeLinList((net.minecraft.nbt.ListTag) foreign); } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); } } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); + return LinStringTag.of(foreign.getAsString()); } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + return LinEndTag.instance(); } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); } /** @@ -869,14 +1009,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + LinListTag.Builder> builder = LinListTag.builder( + LinTagType.fromId(LinTagId.fromId(foreign.getElementType())) + ); for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); + builder.add(toNativeLin(tag)); } - return values.build(); + return builder.build(); } /** @@ -886,44 +1028,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter foreign) { if (foreign == null) { return null; } - if (foreign instanceof CompoundBinaryTag) { + if (foreign instanceof LinCompoundTag compoundTag) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); + for (var entry : compoundTag.value().entrySet()) { + tag.put(entry.getKey(), fromNativeLin(entry.getValue())); } return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag) { + } else if (foreign instanceof LinByteTag byteTag) { + return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte()); + } else if (foreign instanceof LinByteArrayTag byteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value()); + } else if (foreign instanceof LinDoubleTag doubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble()); + } else if (foreign instanceof LinFloatTag floatTag) { + return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat()); + } else if (foreign instanceof LinIntTag intTag) { + return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt()); + } else if (foreign instanceof LinIntArrayTag intArrayTag) { + return new net.minecraft.nbt.IntArrayTag(intArrayTag.value()); + } else if (foreign instanceof LinLongArrayTag longArrayTag) { + return new net.minecraft.nbt.LongArrayTag(longArrayTag.value()); + } else if (foreign instanceof LinListTag listTag) { net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - ListBinaryTag foreignList = (ListBinaryTag) foreign; - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); + for (var t : listTag.value()) { + tag.add(fromNativeLin(t)); } return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { + } else if (foreign instanceof LinLongTag longTag) { + return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong()); + } else if (foreign instanceof LinShortTag shortTag) { + return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort()); + } else if (foreign instanceof LinStringTag stringTag) { + return net.minecraft.nbt.StringTag.valueOf(stringTag.value()); + } else if (foreign instanceof LinEndTag) { return net.minecraft.nbt.EndTag.INSTANCE; } else { throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); @@ -962,7 +1103,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter. */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -29,18 +29,19 @@ import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; +import com.mojang.datafixers.DSL; import com.mojang.datafixers.DSL.TypeReference; import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.core.Direction; import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.StringTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.GsonHelper; import net.minecraft.util.StringUtil; import net.minecraft.util.datafix.DataFixers; @@ -48,7 +49,9 @@ import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.item.DyeColor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -62,7 +65,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; -import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) @@ -76,18 +78,17 @@ import javax.annotation.Nullable; * receive the source version in the compound */ @SuppressWarnings({ "rawtypes", "unchecked" }) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { +public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - //FAWE start - BinaryTag @SuppressWarnings("unchecked") @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); + return (T) fixChunk((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); + return (T) fixBlockEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); + return (T) fixEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -98,24 +99,23 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return original; } - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); + private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); + private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); + private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt); net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - //FAWE end private String fixBlockState(String blockState, int srcVer) { net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); @@ -173,7 +173,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final int LEGACY_VERSION = 1343; private static int DATA_VERSION; - static PaperweightDataConverters INSTANCE; + public static PaperweightDataConverters INSTANCE; private final Map> converters = new EnumMap<>(LegacyType.class); private final Map> inspectors = new EnumMap<>(LegacyType.class); @@ -204,7 +204,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } } - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { + public PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { super(dataVersion); DATA_VERSION = dataVersion; INSTANCE = this; @@ -221,7 +221,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } @Override - public DataFixer buildOptimized(Executor executor) { + public DataFixer buildOptimized(final Set requiredTypes, Executor executor) { return buildUnoptimized(); } @@ -1907,7 +1907,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { try { - object = Component.Serializer.fromJson(s); + object = Component.Serializer.fromJson(s, MinecraftServer.getServer().registryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -1915,7 +1915,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s); + object = Component.Serializer.fromJsonLenient(s, MinecraftServer.getServer().registryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -1929,7 +1929,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo object = Component.literal(""); } - nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); + nbttaglist.set(i, StringTag.valueOf(Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess()))); } nbttagcompound1.put("pages", nbttaglist); @@ -2571,7 +2571,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { try { - object = Component.Serializer.fromJson(s1); + object = Component.Serializer.fromJson(s1, MinecraftServer.getServer().registryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -2579,7 +2579,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s1); + object = Component.Serializer.fromJsonLenient(s1, MinecraftServer.getServer().registryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -2593,7 +2593,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo object = Component.literal(""); } - nbttagcompound.putString(s, Component.Serializer.toJson(object)); + nbttagcompound.putString(s, Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess())); } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java similarity index 80% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightFakePlayer.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java index 874b5323f..baeec90ba 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightFakePlayer.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java @@ -17,17 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.mojang.authlib.GameProfile; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -38,9 +40,12 @@ import java.util.UUID; class PaperweightFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false + ); PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } @Override @@ -67,7 +72,7 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void updateOptions(ServerboundClientInformationPacket packet) { + public void updateOptions(ClientInformation clientOptions) { } @Override @@ -88,6 +93,6 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void openTextEdit(SignBlockEntity sign) { + public void openTextEdit(SignBlockEntity sign, boolean front) { } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java similarity index 83% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java index 32d5682b1..c83733bf2 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R2/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java @@ -17,27 +17,29 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; -import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; @@ -70,8 +72,8 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess EmptyBlockGetter + return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); } @Override @@ -126,27 +112,28 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; + return blockState.getPistonPushReaction() == PushReaction.DESTROY; } @Override public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; + return blockState.getPistonPushReaction() == PushReaction.BLOCK; } @Override public boolean isTicksRandomly() { - return block.isRandomlyTicking(blockState); + return blockState.isRandomlyTicking(); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return material.isSolid(); + return blockState.blocksMotion(); } @Override public boolean isBurnable() { - return material.isFlammable(); + return craftMaterial.isBurnable(); } @Override @@ -157,12 +144,12 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); + return blockState.canBeReplaced(); } @Override public boolean isTranslucent() { - return isTranslucent; + return !blockState.canOcclude(); } @Override @@ -176,14 +163,14 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } @Override public int getMapColor() { // rgb field - return material.getColor().col; + return block.defaultMapColor().col; } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java similarity index 73% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java index 7cfce755e..692e03a94 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java @@ -1,29 +1,25 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter; +import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.NbtUtils; -import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Codec; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R2.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.regen.PaperweightRegen; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen.PaperweightRegen; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -39,18 +35,14 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemType; @@ -58,9 +50,12 @@ import com.sk89q.worldedit.world.registry.BlockMaterial; import io.papermc.lib.PaperLib; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -71,31 +66,29 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.StringRepresentable; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.TreeType; +import org.bukkit.World; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_19_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_19_R2.CraftServer; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlockState; -import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_19_R2.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.entity.Player; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -111,17 +104,20 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import static net.minecraft.core.registries.Registries.BIOME; -public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements - IDelegateBukkitImplAdapter { +public final class PaperweightFaweAdapter extends FaweAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); static { try { @@ -130,18 +126,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } } - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); + super(new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter()); + } + + public Function blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); } @Nullable @@ -254,11 +248,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BlockState getBlock(Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -274,12 +267,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BaseBlock getFullBlock(final Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -293,8 +285,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements // Read the NBT data BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()); + return state.toBaseBlock((LinCompoundTag) toNativeLin(tag)); } } @@ -306,60 +298,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements return SideEffectSet.defaults().getSideEffectsToApply(); } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { - CraftChunk craftChunk = (CraftChunk) chunk; - LevelChunk levelChunk = craftChunk.getHandle(); - Level level = levelChunk.getLevel(); - - BlockPos blockPos = new BlockPos(x, y, z); - net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - LevelChunkSection[] levelChunkSections = levelChunk.getSections(); - int y4 = y >> 4; - LevelChunkSection section = levelChunkSections[y4]; - - net.minecraft.world.level.block.state.BlockState existing; - if (section == null) { - existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); - } else { - existing = section.getBlockState(x & 15, y & 15, z & 15); - } - - levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity - - CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null; - if (compoundTag != null || existing instanceof TileEntityBlock) { - level.setBlock(blockPos, blockState, 0); - // remove tile - if (compoundTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - BlockEntity blockEntity = level.getBlockEntity(blockPos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - blockEntity.load(tag); // readTagIntoTileEntity - load data - } - } - } else { - if (existing == blockState) { - return true; - } - levelChunk.setBlockState(blockPos, blockState, false); - } - if (update) { - level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0); - } - return true; - } - @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); + return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); } @Override @@ -373,14 +314,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements if (id != null) { EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { + Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); + final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag); + final Map> tags = NbtUtils.getLinCompoundTagValues(tag); + tags.put("Id", LinStringTag.of(id)); + return LinCompoundTag.of(tags); }; return new LazyBaseEntity(type, saveTag); } else { @@ -504,7 +445,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); + ServerLevel nmsWorld = getServerLevel(world); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); if (map != null && wasAccessibleSinceLastSave(map)) { boolean flag = false; @@ -542,72 +483,64 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements int internalId = BlockStateIdAccess.getBlockStateId(blockState); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) + getServerLevel(world), + new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z()) ); } @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); ItemStack stack = new ItemStack( - DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM) - .get(ResourceLocation.tryParse(baseItemStack.getType().getId())), + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())), baseItemStack.getAmount() ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()); + if (nbt != null) { + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); + } return CraftItemStack.asCraftMirror(stack); } @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; + protected void preCaptureStates(final ServerLevel serverLevel) { + serverLevel.captureTreeGeneration = true; + serverLevel.captureBlockStates = true; + } + + @Override + protected List getCapturedBlockStatesCopy(final ServerLevel serverLevel) { + return new ArrayList<>(serverLevel.capturedBlockStates.values()); + } + + @Override + protected void postCaptureBlockStates(final ServerLevel serverLevel) { + serverLevel.captureBlockStates = false; + serverLevel.captureTreeGeneration = false; + serverLevel.capturedBlockStates.clear(); + } + + @Override + protected ServerLevel getServerLevel(final World world) { + return ((CraftWorld) world).getHandle(); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; + final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), + itemStack.getAmount() + ); } @Override @@ -639,7 +572,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements .getServer() .registryAccess() .registryOrThrow(BIOME); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); + ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id()); Biome biome = registry.get(resourceLocation); return registry.getId(biome); } diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java index 282a6b505..4fa9988b8 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; @@ -9,21 +9,22 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -102,7 +103,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess currentTick; if (nextTick || cachedChanges.size() >= 1024) { if (nextTick) { @@ -132,15 +133,15 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; + private final IntPair chunkPos; private final int minHeight; private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -130,6 +143,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc this.blockLight = new DataLayer[getSectionCount()]; this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); } public int getChunkX() { @@ -146,13 +160,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + // Increment regardless of whether copy will be created or not to return null from getCopy() + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -236,23 +265,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -272,8 +302,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( LightLayer.BLOCK, sectionPos, - dataLayer, - true + dataLayer ); } skyLight[alayer] = dataLayer; @@ -300,7 +329,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc Arrays.fill(LAYER_COUNT, (byte) 15); dataLayer = new DataLayer(LAYER_COUNT); ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true + dataLayer ); } blockLight[alayer] = dataLayer; @@ -316,14 +345,22 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + public @Nullable FaweCompoundTag entity(final UUID uuid) { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -331,13 +368,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { + ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -350,10 +388,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -365,12 +403,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -387,12 +425,19 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - // Remove existing tiles. Create a copy so that we can remove blocks Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -464,6 +509,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -481,7 +528,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } } } else { - setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes()); + PalettedContainer> paletteBiomes = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + if (paletteBiomes != null) { + PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes); + } } } } @@ -523,13 +577,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (existingSection == null) { PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, @@ -539,6 +588,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -595,16 +646,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc existingSection.getBiomes() ); - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - adapter, - biomeRegistry, - biomeData - ); + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + this::loadPrivately, + setArr, + adapter, + biomeRegistry, + biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() + ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -678,7 +730,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -690,48 +742,47 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + entity.setUUID(NbtUtils.uuid(nativeTag)); + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -746,34 +797,33 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; + final int x = blockHash.x() + bx; + final int y = blockHash.y(); + final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); - tileEntity.load(tag); + tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess()); } } } @@ -785,15 +835,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified nmsChunk.mustNotSave = false; nmsChunk.setUnsaved(true); // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); + if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) { + this.send(); } if (finalizer != null) { finalizer.run(); @@ -815,7 +864,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (callback == null) { if (finalizer != null) { - finalizer.run(); + queueHandler.async(finalizer, null); } return null; } else { @@ -881,9 +930,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -891,8 +938,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send() { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); + } } /** @@ -1003,9 +1052,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); @@ -1051,8 +1098,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( lightLayer, sectionPos, - dataLayer, - true + dataLayer ); } synchronized (dataLayer) { @@ -1075,38 +1121,25 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int sectionIndex, final PalettedContainerRO> data ) { - PalettedContainer> biomeData; - if (data instanceof PalettedContainer> palettedContainer) { - biomeData = palettedContainer; - } else { - LOGGER.warn( - "Cannot correctly set biomes to world, existing biomes may be lost. Expected class " + - "type {} but got {}", - PalettedContainer.class.getSimpleName(), - data.getClass().getSimpleName() - ); - biomeData = data.recreate(); - } BiomeType[] sectionBiomes; if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { - return biomeData; + return null; } + PalettedContainer> biomeData = data.recreate(); for (int y = 0, index = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { for (int x = 0; x < 4; x++, index++) { BiomeType biomeType = sectionBiomes[index]; if (biomeType == null) { - continue; + biomeData.set(x, y, z, data.get(x, y, z)); + } else { + biomeData.set( + x, + y, + z, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType)) + ); } - biomeData.set( - x, - y, - z, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)) - ); } } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightGetBlocks_Copy.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java index c56de7093..7d199c7f6 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java @@ -1,21 +1,23 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -24,8 +26,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -37,14 +42,14 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; final LevelChunk levelChunk; - private PalettedContainer>[] biomes = null; + private Holder[][] biomes = null; protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.levelChunk = levelChunk; @@ -55,44 +60,37 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId(DedicatedServer + .getServer() + .registryAccess()))) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -105,7 +103,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -142,7 +141,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BiomeType getBiomeType(int x, int y, int z) { - Holder biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2); + Holder biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2]; return PaperweightPlatformAdapter.adapt(biome, serverLevel); } @@ -171,10 +170,25 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { if (biomes == null) { - biomes = new PalettedContainer[getSectionCount()]; + biomes = new Holder[getSectionCount()][]; + } + if (biomes[layer] == null) { + biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - biomes[layer] = palettedContainer.copy(); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } else { LOGGER.error( "Cannot correctly save biomes to history. Expected class type {} but got {}", @@ -187,7 +201,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -199,6 +213,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } @@ -213,6 +231,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java index 9189ca251..9e226b088 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -235,19 +263,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } try { synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); PalettedContainer blocks = section.getStates(); - ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject( - blocks, - fieldThreadingDetectorOffset - ); + ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks); synchronized (currentThreadingDetector) { - Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset); + Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector); if (currentLock instanceof DelegateSemaphore delegateSemaphore) { return delegateSemaphore; } DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock); + fieldLock.set(currentThreadingDetector, newLock); return newLock; } } @@ -283,8 +307,23 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); try { - CraftChunk chunk = (CraftChunk) future.get(); - return chunk.getHandle(); + CraftChunk chunk; + try { + chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + } catch (TimeoutException e) { + String world = serverLevel.getWorld().getName(); + // We've already taken 10 seconds we can afford to wait a little here. + boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + if (loaded) { + LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); + // Retry chunk load + chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + } else { + throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); + } + } + addTicket(serverLevel, chunkX, chunkZ); + return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); } catch (Throwable e) { e.printStackTrace(); } @@ -296,7 +335,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { // Ensure chunk is definitely loaded before applying a ticket io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel .getChunkSource() - .addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { @@ -309,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -318,40 +357,42 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { LevelChunk levelChunk; if (PaperLib.isPaper()) { // getChunkAtIfLoadedImmediately is paper only - levelChunk = nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ); + levelChunk = nmsWorld.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = ((Optional) ((Either) chunkHolder - .getTickingChunkFuture() // method is not present with new paper chunk system - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) - .orElse(null); + levelChunk = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); } if (levelChunk == null) { return; } - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true - ); + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } + MinecraftServer.getServer().execute(() -> { + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } @@ -381,7 +422,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @Nullable PalettedContainer> biomes ) { if (set == null) { - return newChunkSection(layer, biomeRegistry, biomes); + return newChunkSection(biomeRegistry, biomes); } final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); @@ -454,12 +495,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { .getBukkitImplAdapter() .getInternalBiomeId( BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); } - return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); + return new LevelChunkSection(blockStatePalettedContainer, biomes); } catch (final Throwable e) { throw e; } finally { @@ -472,20 +512,26 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @SuppressWarnings("deprecation") // Only deprecated in paper private static LevelChunkSection newChunkSection( - int layer, Registry biomeRegistry, @Nullable PalettedContainer> biomes ) { if (biomes == null) { - return new LevelChunkSection(layer, biomeRegistry); + return new LevelChunkSection(biomeRegistry); } PalettedContainer dataPaletteBlocks = new PalettedContainer<>( Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), - PalettedContainer.Strategy.SECTION_STATES, - null + PalettedContainer.Strategy.SECTION_STATES ); - return new LevelChunkSection(layer, dataPaletteBlocks, biomes); + return new LevelChunkSection(dataPaletteBlocks, biomes); + } + + public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer> biomes) { + try { + fieldBiomes.set(section, biomes); + } catch (IllegalAccessException e) { + LOGGER.error("Could not set biomes to chunk section", e); + } } /** @@ -522,8 +568,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { PalettedContainer> biomePalettedContainer = new PalettedContainer<>( biomeRegistry, biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); final Palette> biomePalette; diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java similarity index 99% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPostProcessor.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java index 4bbf3baca..bc094a916 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java new file mode 100644 index 000000000..c7b61575c --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java @@ -0,0 +1,77 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; + +import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.util.Unit; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.status.ChunkStatus; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.IntConsumer; + +public class PaperweightStarlightRelighter extends StarlightRelighter { + + private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); + + public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + super(serverLevel, queue); + } + + @Override + protected ChunkPos createChunkPos(final long chunkKey) { + return new ChunkPos(chunkKey); + } + + @Override + protected long asLong(final int chunkX, final int chunkZ) { + return ChunkPos.asLong(chunkX, chunkZ); + } + + @Override + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); + } + + protected void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ) { + try { + serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); + } catch (Exception e) { + LOGGER.error("Error occurred on relighting", e); + } + } + + /* + * Allow the server to unload the chunks again. + * Also, if chunk packets are sent delayed, we need to do that here + */ + protected void postProcessChunks(Set coords) { + boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; + for (ChunkPos pos : coords) { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(new IntPair(x, z), serverLevel, x, z); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighterFactory.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java index ad525f242..1425088b8 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighterFactory.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java @@ -1,23 +1,20 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; +import org.bukkit.craftbukkit.CraftWorld; import javax.annotation.Nonnull; public class PaperweightStarlightRelighterFactory implements RelighterFactory { @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { org.bukkit.World w = Bukkit.getWorld(world.getName()); if (w == null) { return NullRelighter.INSTANCE; diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java similarity index 91% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/nbt/PaperweightLazyCompoundTag.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java index 9ff3c1f61..52111a4fd 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/nbt/PaperweightLazyCompoundTag.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2.nbt; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.LazyCompoundTag; @@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.nbt.NumericTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.ArrayList; import java.util.Collections; @@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { @Override @SuppressWarnings("unchecked") - public Map getValue() { + public Map> getValue() { if (compoundTag == null) { compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); } @@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @Override - public CompoundBinaryTag asBinaryTag() { + public LinCompoundTag toLinTag() { getValue(); - return compoundTag.asBinaryTag(); + return compoundTag.toLinTag(); } public boolean containsKey(String key) { @@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key) { + public List> getList(String key) { net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); for (net.minecraft.nbt.Tag elem : nbtList) { if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { list.add(new PaperweightLazyCompoundTag(compoundTag)); @@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { + public > List getList(String key, Class listType) { ListTag listTag = getListTag(key); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java new file mode 100644 index 000000000..d80d098ff --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java @@ -0,0 +1,302 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen; + +import com.fastasyncworldedit.bukkit.adapter.Regenerator; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.queue.IChunkCache; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.RegenOptions; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.generator.BiomeProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightRegen extends Regenerator { + + private static final Field serverWorldsField; + private static final Field paperConfigField; + private static final Field generatorSettingBaseSupplierField; + + + static { + try { + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + Field tmpPaperConfigField; + try { //only present on paper + tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); + tmpPaperConfigField.setAccessible(true); + } catch (Exception e) { + tmpPaperConfigField = null; + } + paperConfigField = tmpPaperConfigField; + + generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( + "settings", "e")); + generatorSettingBaseSupplierField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //runtime + private ServerLevel originalServerWorld; + private ServerLevel freshWorld; + private LevelStorageSource.LevelStorageAccess session; + + private Path tempDir; + + public PaperweightRegen( + World originalBukkitWorld, + Region region, + Extent target, + RegenOptions options + ) { + super(originalBukkitWorld, region, target, options); + } + + @Override + protected void runTasks(final BooleanSupplier shouldKeepTicking) { + while (shouldKeepTicking.getAsBoolean()) { + if (!this.freshWorld.getChunkSource().pollTask()) { + return; + } + } + } + + @Override + protected boolean prepare() { + this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); + seed = options.getSeed().orElse(originalServerWorld.getSeed()); + return true; + } + + @Override + protected boolean initNewWorld() throws Exception { + //world folder + tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + + //prepare for world init (see upstream implementation for reference) + org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); + org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); + ResourceKey levelStemResourceKey = getWorldDimKey(environment); + session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); + PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; + + MinecraftServer server = originalServerWorld.getCraftServer().getServer(); + WorldOptions originalOpts = originalWorldData.worldGenOptions(); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + LevelSettings newWorldSettings = new LevelSettings( + "faweregentempworld", + originalWorldData.settings.gameType(), + originalWorldData.settings.hardcore(), + originalWorldData.settings.difficulty(), + originalWorldData.settings.allowCommands(), + originalWorldData.settings.gameRules(), + originalWorldData.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + originalWorldData.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : originalWorldData.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + BiomeProvider biomeProvider = getBiomeProvider(); + + + //init world + freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( + server, + server.executor, + session, + newWorldData, + originalServerWorld.dimension(), + new LevelStem( + originalServerWorld.dimensionTypeRegistration(), + originalServerWorld.getChunkSource().getGenerator() + ), + new RegenNoOpWorldLoadListener(), + originalServerWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalServerWorld.getRandomSequences(), + environment, + generator, + biomeProvider + ) { + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; + + @Override + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + if (options.hasBiomeType()) { + return singleBiome; + } + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } + }).get(); + freshWorld.noSave = true; + removeWorldFromWorldsMap(); + newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name + if (paperConfigField != null) { + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); + } + return true; + } + + @Override + protected void cleanup() { + try { + session.close(); + } catch (Exception ignored) { + } + + //shutdown chunk provider + try { + Fawe.instance().getQueueHandler().sync(() -> { + try { + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ignored) { + } + + //remove world from server + try { + Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); + } catch (Exception ignored) { + } + + //delete directory + try { + SafeFiles.tryHardToDeleteDir(tempDir); + } catch (Exception ignored) { + } + } + + @Override + protected IChunkCache initSourceQueueCache() { + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); + } + + //util + @SuppressWarnings("unchecked") + private void removeWorldFromWorldsMap() { + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { + return switch (env) { + case NETHER -> LevelStem.NETHER; + case THE_END -> LevelStem.END; + default -> LevelStem.OVERWORLD; + }; + } + + private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { + + private RegenNoOpWorldLoadListener() { + } + + @Override + public void updateSpawnPos(@NotNull ChunkPos spawnPos) { + } + + @Override + public void onStatusChange( + final @NotNull ChunkPos pos, + @org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status + ) { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + } + + // TODO Paper only(?) @Override + public void setChunkRadius(int radius) { + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts new file mode 100644 index 000000000..4164c6262 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -0,0 +1,17 @@ +import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension + +plugins { + java +} + +applyPaperweightAdapterConfiguration() + +repositories { + gradlePluginPortal() +} + +dependencies { + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ + the().paperDevBundle("1.21.1-R0.1-20241121.101634-127") + compileOnly(libs.paperlib) +} diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java new file mode 100644 index 000000000..125d000bf --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java @@ -0,0 +1,1158 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.Futures; +import com.mojang.serialization.Codec; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.extension.platform.Watchdog; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.internal.Constants; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.registry.state.BooleanProperty; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; +import com.sk89q.worldedit.registry.state.IntegerProperty; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.DataFixer; +import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeCategory; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.entity.EntityTypes; +import com.sk89q.worldedit.world.item.ItemType; +import net.minecraft.SharedConstants; +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ChunkResult; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.RandomSource; +import net.minecraft.util.StringRepresentable; +import net.minecraft.util.thread.BlockableEventLoop; +import net.minecraft.world.Clearable; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.StructureBlockEntity; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.generator.ChunkGenerator; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinEndTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; +import org.spigotmc.SpigotConfig; +import org.spigotmc.WatchdogThread; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class PaperweightAdapter implements BukkitImplAdapter { + + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + + private final Field serverWorldsField; + private final Method getChunkFutureMethod; + private final Field chunkProviderExecutorField; + private final PaperweightDataConverters dataFixer; + private final Watchdog watchdog; + + private static final RandomSource random = RandomSource.create(); + + // ------------------------------------------------------------------------ + // Code that may break between versions of Minecraft + // ------------------------------------------------------------------------ + + public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { + // A simple test + CraftServer.class.cast(Bukkit.getServer()); + + int dataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion(); + if (dataVersion != 3953 && dataVersion != 3955) { + throw new UnsupportedClassVersionError("Not 1.21(.1)!"); + } + + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod( + StaticRefraction.GET_CHUNK_FUTURE_MAIN_THREAD, + int.class, int.class, ChunkStatus.class, boolean.class + ); + getChunkFutureMethod.setAccessible(true); + + chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField( + StaticRefraction.MAIN_THREAD_PROCESSOR + ); + chunkProviderExecutorField.setAccessible(true); + + this.dataFixer = new PaperweightDataConverters(dataVersion, this); + + Watchdog watchdog; + try { + Class.forName("org.spigotmc.WatchdogThread"); + watchdog = new SpigotWatchdog(); + } catch (ClassNotFoundException | NoSuchFieldException e) { + try { + watchdog = new MojangWatchdog(((CraftServer) Bukkit.getServer()).getServer()); + } catch (NoSuchFieldException ex) { + watchdog = null; + } + } + this.watchdog = watchdog; + + try { + Class.forName("org.spigotmc.SpigotConfig"); + SpigotConfig.config.set("world-settings.worldeditregentempworld.verbose", false); + } catch (ClassNotFoundException ignored) { + } + } + + @Override + public DataFixer getDataFixer() { + return this.dataFixer; + } + + /** + * Read the given NBT data into the given tile entity. + * + * @param tileEntity the tile entity + * @param tag the tag + */ + static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) { + tileEntity.loadWithComponents(tag, MinecraftServer.getServer().registryAccess()); + tileEntity.setChanged(); + } + + /** + * Get the ID string of the given entity. + * + * @param entity the entity + * @return the entity ID + */ + private static String getEntityId(Entity entity) { + return EntityType.getKey(entity.getType()).toString(); + } + + /** + * Create an entity using the given entity ID. + * + * @param id the entity ID + * @param world the world + * @return an entity or null + */ + @Nullable + private static Entity createEntityFromId(String id, net.minecraft.world.level.Level world) { + return EntityType.byString(id).map(t -> t.create(world)).orElse(null); + } + + /** + * Write the given NBT data into the given entity. + * + * @param entity the entity + * @param tag the tag + */ + private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { + entity.load(tag); + } + + /** + * Write the entity's NBT data to the given tag. + * + * @param entity the entity + * @param tag the tag + */ + private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) { + entity.save(tag); + } + + private static Block getBlockFromType(BlockType blockType) { + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id())); + } + + private static Item getItemFromType(ItemType itemType) { + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(itemType.id())); + } + + @Override + public OptionalInt getInternalBlockStateId(BlockData data) { + net.minecraft.world.level.block.state.BlockState state = ((CraftBlockData) data).getState(); + int combinedId = Block.getId(state); + return combinedId == 0 && state.getBlock() != Blocks.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); + } + + @Override + public OptionalInt getInternalBlockStateId(BlockState state) { + Block mcBlock = getBlockFromType(state.getBlockType()); + net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); + Map, Object> states = state.getStates(); + newState = applyProperties(mcBlock.getStateDefinition(), newState, states); + final int combinedId = Block.getId(newState); + return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); + } + + public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + int internalId = Block.getId(blockState); + BlockState state = BlockStateIdAccess.getBlockStateById(internalId); + if (state == null) { + state = BukkitAdapter.adapt(CraftBlockData.createData(blockState)); + } + + return state; + } + + public BiomeType adapt(Biome biome) { + var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(biome); + if (mcBiome == null) { + return null; + } + return BiomeType.REGISTRY.get(mcBiome.toString()); + } + + public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) { + int internalId = BlockStateIdAccess.getBlockStateId(blockState); + return Block.stateById(internalId); + } + + @Override + public BlockState getBlock(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); + return adapt(blockData); + } + + @Override + public BaseBlock getFullBlock(Location location) { + BlockState state = getBlock(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + + // Read the NBT data + BlockEntity te = chunk.getBlockEntity(blockPos); + if (te != null) { + net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess()); + return state.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))); + } + + return state.toBaseBlock(); + } + + private static final HashMap> biomeTypeToNMSCache = new HashMap<>(); + private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); + + @Override + public BiomeType getBiome(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + + return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString())); + } + + @Override + public void setBiome(Location location, BiomeType biome) { + checkNotNull(location); + checkNotNull(biome); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, ResourceLocation.parse(b.id()))))); + chunk.setUnsaved(true); + } + + @Override + public WorldNativeAccess createWorldNativeAccess(World world) { + return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); + } + + private static net.minecraft.core.Direction adapt(Direction face) { + switch (face) { + case NORTH: + return net.minecraft.core.Direction.NORTH; + case SOUTH: + return net.minecraft.core.Direction.SOUTH; + case WEST: + return net.minecraft.core.Direction.WEST; + case EAST: + return net.minecraft.core.Direction.EAST; + case DOWN: + return net.minecraft.core.Direction.DOWN; + case UP: + default: + return net.minecraft.core.Direction.UP; + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private net.minecraft.world.level.block.state.BlockState applyProperties( + StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, + Map, Object> states + ) { + for (Map.Entry, Object> state : states.entrySet()) { + net.minecraft.world.level.block.state.properties.Property property = + stateContainer.getProperty(state.getKey().getName()); + Comparable value = (Comparable) state.getValue(); + // we may need to adapt this value, depending on the source prop + if (property instanceof DirectionProperty) { + Direction dir = (Direction) value; + value = adapt(dir); + } else if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + String enumName = (String) value; + value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property) + .getValue(enumName).orElseThrow(() -> + new IllegalStateException( + "Enum property " + property.getName() + " does not contain " + enumName + ) + ); + } + + newState = newState.setValue( + (net.minecraft.world.level.block.state.properties.Property) property, + (Comparable) value + ); + } + return newState; + } + + @Override + public BaseEntity getEntity(org.bukkit.entity.Entity entity) { + checkNotNull(entity); + + CraftEntity craftEntity = ((CraftEntity) entity); + Entity mcEntity = craftEntity.getHandle(); + + // Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity + if (mcEntity.isPassenger()) { + return null; + } + + String id = getEntityId(mcEntity); + + net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + readEntityIntoTag(mcEntity, tag); + return new BaseEntity( + EntityTypes.get(id), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)) + ); + } + + @Nullable + @Override + public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) { + checkNotNull(location); + checkNotNull(state); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + ServerLevel worldServer = craftWorld.getHandle(); + + String entityId = state.getType().id(); + + LinCompoundTag nativeTag = state.getNbt(); + net.minecraft.nbt.CompoundTag tag; + if (nativeTag != null) { + tag = (net.minecraft.nbt.CompoundTag) fromNativeLin(nativeTag); + removeUnwantedEntityTagsRecursively(tag); + } else { + tag = new net.minecraft.nbt.CompoundTag(); + } + + tag.putString("id", entityId); + + Entity createdEntity = EntityType.loadEntityRecursive(tag, craftWorld.getHandle(), (loadedEntity) -> { + loadedEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + return loadedEntity; + }); + + if (createdEntity != null) { + worldServer.addFreshEntityWithPassengers(createdEntity, SpawnReason.CUSTOM); + return createdEntity.getBukkitEntity(); + } else { + return null; + } + } + + // This removes all unwanted tags from the main entity and all its passengers + private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) { + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + + // Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive + if (tag.contains("Passengers", LinTagId.LIST.id())) { + net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", LinTagId.COMPOUND.id()); + + for (int i = 0; i < nbttaglist.size(); ++i) { + removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i)); + } + } + } + + @Override + public Component getRichBlockName(BlockType blockType) { + return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); + } + + @Override + public Component getRichItemName(ItemType itemType) { + return TranslatableComponent.of(getItemFromType(itemType).getDescriptionId()); + } + + @Override + public Component getRichItemName(BaseItemStack itemStack) { + return TranslatableComponent.of(CraftItemStack.asNMSCopy(BukkitAdapter.adapt(itemStack)).getDescriptionId()); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final LoadingCache> PROPERTY_CACHE = CacheBuilder + .newBuilder() + .build(new CacheLoader<>() { + @Override + public Property load(net.minecraft.world.level.block.state.properties.Property state) { + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + return new DirectionalProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> Direction.valueOf(((StringRepresentable) e) + .getSerializedName() + .toUpperCase(Locale.ROOT))) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + return new EnumProperty( + state.getName(), + new ArrayList<>((List) state + .getPossibleValues() + .stream() + .map(e -> ((StringRepresentable) e).getSerializedName()) + .toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state + .getClass() + .getSimpleName()); + } + } + }); + + @SuppressWarnings({ "rawtypes" }) + @Override + public Map> getProperties(BlockType blockType) { + Map> properties = new TreeMap<>(); + Block block = getBlockFromType(blockType); + StateDefinition blockStateList = + block.getStateDefinition(); + for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { + Property property = PROPERTY_CACHE.getUnchecked(state); + properties.put(property.getName(), property); + } + return properties; + } + + @Override + public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) { + var structureBlock = new StructureBlockEntity( + new BlockPos(pos.x(), pos.y(), pos.z()), + Blocks.STRUCTURE_BLOCK.defaultBlockState() + ); + structureBlock.setLevel(((CraftPlayer) player).getHandle().level()); + ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create( + structureBlock, + (blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData) + )); + } + + @Override + public void sendFakeOP(Player player) { + ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( + ((CraftPlayer) player).getHandle(), (byte) 28 + )); + } + + /** + * For serializing and deserializing components. + */ + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + + @Override + public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + var registryAccess = DedicatedServer.getServer().registryAccess(); + ItemStack stack = new ItemStack( + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())), + baseItemStack.getAmount() + ); + LinCompoundTag nbt = baseItemStack.getNbt(); + if (nbt != null) { + DataComponentPatch componentPatch = COMPONENTS_CODEC.parse( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + fromNativeLin(nbt) + ).getOrThrow(); + stack.applyComponents(componentPatch); + } + return CraftItemStack.asCraftMirror(stack); + } + + @Override + public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + var registryAccess = DedicatedServer.getServer().registryAccess(); + final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), itemStack.getAmount()); + } + + private final LoadingCache fakePlayers + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); + + @Override + public boolean simulateItemUse(World world, BlockVector3 position, BaseItem item, Direction face) { + CraftWorld craftWorld = (CraftWorld) world; + ServerLevel worldServer = craftWorld.getHandle(); + ItemStack stack = CraftItemStack.asNMSCopy(adapt( + item instanceof BaseItemStack + ? ((BaseItemStack) item) + : new BaseItemStack(item.getType(), item.getNbtReference(), 1) + )); + + PaperweightFakePlayer fakePlayer; + try { + fakePlayer = fakePlayers.get(worldServer); + } catch (ExecutionException ignored) { + return false; + } + fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); + fakePlayer.absMoveTo(position.x(), position.y(), position.z(), + (float) face.toVector().toYaw(), (float) face.toVector().toPitch()); + + final BlockPos blockPos = new BlockPos(position.x(), position.y(), position.z()); + final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos); + final net.minecraft.core.Direction enumFacing = adapt(face); + BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false); + UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace); + InteractionResult result = stack.useOn(context); + if (result != InteractionResult.SUCCESS) { + if (worldServer.getBlockState(blockPos).useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) { + result = InteractionResult.SUCCESS; + } else { + result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult(); + } + } + + return result == InteractionResult.SUCCESS; + } + + @Override + public boolean canPlaceAt(World world, BlockVector3 position, BlockState blockState) { + int internalId = BlockStateIdAccess.getBlockStateId(blockState); + net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId); + return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z())); + } + + @Override + public boolean regenerate(World bukkitWorld, Region region, Extent extent, RegenOptions options) { + try { + doRegen(bukkitWorld, region, extent, options); + } catch (Exception e) { + throw new IllegalStateException("Regen failed.", e); + } + + return true; + } + + private void doRegen(World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception { + Environment env = bukkitWorld.getEnvironment(); + ChunkGenerator gen = bukkitWorld.getGenerator(); + + Path tempDir = Files.createTempDirectory("WorldEditWorldGen"); + LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); + ResourceKey worldDimKey = getWorldDimKey(env); + try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("worldeditregentempworld", worldDimKey)) { + ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); + PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() + .getWorldData().overworldData(); + WorldOptions originalOpts = levelProperties.worldGenOptions(); + + long seed = options.getSeed().orElse(originalWorld.getSeed()); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + + LevelSettings newWorldSettings = new LevelSettings( + "worldeditregentempworld", + levelProperties.settings.gameType(), + levelProperties.settings.hardcore(), + levelProperties.settings.difficulty(), + levelProperties.settings.allowCommands(), + levelProperties.settings.gameRules(), + levelProperties.settings.getDataConfiguration() + ); + + @SuppressWarnings("deprecation") + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + levelProperties.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : levelProperties.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + ServerLevel freshWorld = new ServerLevel( + originalWorld.getServer(), + originalWorld.getServer().executor, + session, newWorldData, + originalWorld.dimension(), + new LevelStem( + originalWorld.dimensionTypeRegistration(), + originalWorld.getChunkSource().getGenerator() + ), + new NoOpWorldLoadListener(), + originalWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalWorld.getRandomSequences(), + env, + gen, + bukkitWorld.getBiomeProvider() + ); + try { + regenForWorld(region, extent, freshWorld, options); + } finally { + freshWorld.getChunkSource().close(false); + } + } finally { + try { + @SuppressWarnings("unchecked") + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("worldeditregentempworld"); + } catch (IllegalAccessException ignored) { + } + SafeFiles.tryHardToDeleteDir(tempDir); + } + } + + private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { + ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registries.BIOME).getKey(origBiome); + if (key == null) { + return null; + } + return BiomeTypes.get(key.toString()); + } + + @SuppressWarnings("unchecked") + private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws WorldEditException { + List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); + BlockableEventLoop executor; + try { + executor = (BlockableEventLoop) chunkProviderExecutorField.get(serverWorld.getChunkSource()); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Couldn't get executor for chunk loading.", e); + } + executor.managedBlock(() -> { + // bail out early if a future fails + if (chunkLoadings.stream().anyMatch(ftr -> + ftr.isDone() && Futures.getUnchecked(ftr) == null + )) { + return false; + } + return chunkLoadings.stream().allMatch(CompletableFuture::isDone); + }); + Map chunks = new HashMap<>(); + for (CompletableFuture future : chunkLoadings) { + @Nullable + ChunkAccess chunk = future.getNow(null); + checkState(chunk != null, "Failed to generate a chunk, regen failed."); + chunks.put(chunk.getPos(), chunk); + } + + for (BlockVector3 vec : region) { + BlockPos pos = new BlockPos(vec.x(), vec.y(), vec.z()); + ChunkAccess chunk = chunks.get(new ChunkPos(pos)); + final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos); + int internalId = Block.getId(blockData); + BlockStateHolder state = BlockStateIdAccess.getBlockStateById(internalId); + Objects.requireNonNull(state); + BlockEntity blockEntity = chunk.getBlockEntity(pos); + if (blockEntity != null) { + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess()); + state = state.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))); + } + extent.setBlock(vec, state.toBaseBlock()); + if (options.shouldRegenBiomes()) { + Biome origBiome = chunk.getNoiseBiome(vec.x(), vec.y(), vec.z()).value(); + BiomeType adaptedBiome = adapt(serverWorld, origBiome); + if (adaptedBiome != null) { + extent.setBiome(vec, adaptedBiome); + } + } + } + } + + @SuppressWarnings("unchecked") + private List> submitChunkLoadTasks(Region region, ServerLevel serverWorld) { + ServerChunkCache chunkManager = serverWorld.getChunkSource(); + List> chunkLoadings = new ArrayList<>(); + // Pre-gen all the chunks + for (BlockVector2 chunk : region.getChunks()) { + try { + //noinspection unchecked + chunkLoadings.add( + ((CompletableFuture>) + getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true)) + .thenApply(either -> either.orElse(null)) + ); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Couldn't load chunk for regen.", e); + } + } + return chunkLoadings; + } + + private ResourceKey getWorldDimKey(Environment env) { + switch (env) { + case NETHER: + return LevelStem.NETHER; + case THE_END: + return LevelStem.END; + case NORMAL: + default: + return LevelStem.OVERWORLD; + } + } + + private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.NEIGHBORS, + SideEffect.LIGHTING, + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.EVENTS, + SideEffect.UPDATE + ); + + @Override + public Set getSupportedSideEffects() { + return SUPPORTED_SIDE_EFFECTS; + } + + @Override + public boolean clearContainerBlockContents(World world, BlockVector3 pt) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z())); + if (entity instanceof Clearable) { + ((Clearable) entity).clearContent(); + return true; + } + return false; + } + + @Override + public void initializeRegistries() { + DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer(); + // Biomes + for (ResourceLocation name : server.registryAccess().registryOrThrow(Registries.BIOME).keySet()) { + if (BiomeType.REGISTRY.get(name.toString()) == null) { + BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString())); + } + } + + // BiomeCategories + Registry biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME); + biomeRegistry.getTagNames().forEach(tagKey -> { + String key = tagKey.location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.getTag(tagKey) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(this::adapt) + .collect(Collectors.toSet())) + ); + } + }); + } + + @Override + public void sendBiomeUpdates(World world, Iterable chunks) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); + for (BlockVector2 chunk : chunks) { + nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); + } + originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + } + + // ------------------------------------------------------------------------ + // Code that is less likely to break + // ------------------------------------------------------------------------ + + /** + * Converts from a non-native NMS NBT structure to a native WorldEdit NBT + * structure. + * + * @param foreign non-native NMS NBT structure + * @return native WorldEdit NBT structure + */ + @Override + public LinTag toNativeLin(net.minecraft.nbt.Tag foreign) { + if (foreign == null) { + return null; + } + if (foreign instanceof net.minecraft.nbt.CompoundTag) { + Map> values = new HashMap<>(); + Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); + + for (String str : foreignKeys) { + net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); + values.put(str, toNativeLin(base)); + } + return LinCompoundTag.of(values); + } else if (foreign instanceof net.minecraft.nbt.ByteTag) { + return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { + return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { + return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + } else if (foreign instanceof net.minecraft.nbt.FloatTag) { + return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + } else if (foreign instanceof net.minecraft.nbt.IntTag) { + return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { + return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { + return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); + } else if (foreign instanceof net.minecraft.nbt.ListTag) { + try { + return toNativeLinList((net.minecraft.nbt.ListTag) foreign); + } catch (Throwable e) { + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); + } + } else if (foreign instanceof net.minecraft.nbt.LongTag) { + return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + } else if (foreign instanceof net.minecraft.nbt.ShortTag) { + return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + } else if (foreign instanceof net.minecraft.nbt.StringTag) { + return LinStringTag.of(foreign.getAsString()); + } else if (foreign instanceof net.minecraft.nbt.EndTag) { + return LinEndTag.instance(); + } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + } + + /** + * Convert a foreign NBT list tag into a native WorldEdit one. + * + * @param foreign the foreign tag + * @return the converted tag + * @throws SecurityException on error + * @throws IllegalArgumentException on error + */ + private LinListTag toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + LinListTag.Builder> builder = LinListTag.builder( + LinTagType.fromId(LinTagId.fromId(foreign.getElementType())) + ); + + for (net.minecraft.nbt.Tag tag : foreign) { + builder.add(toNativeLin(tag)); + } + + return builder.build(); + } + + /** + * Converts a WorldEdit-native NBT structure to a NMS structure. + * + * @param foreign structure to convert + * @return non-native structure + */ + @Override + public net.minecraft.nbt.Tag fromNativeLin(LinTag foreign) { + if (foreign == null) { + return null; + } + if (foreign instanceof LinCompoundTag compoundTag) { + net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + for (var entry : compoundTag.value().entrySet()) { + tag.put(entry.getKey(), fromNativeLin(entry.getValue())); + } + return tag; + } else if (foreign instanceof LinByteTag byteTag) { + return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte()); + } else if (foreign instanceof LinByteArrayTag byteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value()); + } else if (foreign instanceof LinDoubleTag doubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble()); + } else if (foreign instanceof LinFloatTag floatTag) { + return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat()); + } else if (foreign instanceof LinIntTag intTag) { + return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt()); + } else if (foreign instanceof LinIntArrayTag intArrayTag) { + return new net.minecraft.nbt.IntArrayTag(intArrayTag.value()); + } else if (foreign instanceof LinLongArrayTag longArrayTag) { + return new net.minecraft.nbt.LongArrayTag(longArrayTag.value()); + } else if (foreign instanceof LinListTag listTag) { + net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); + for (var t : listTag.value()) { + tag.add(fromNativeLin(t)); + } + return tag; + } else if (foreign instanceof LinLongTag longTag) { + return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong()); + } else if (foreign instanceof LinShortTag shortTag) { + return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort()); + } else if (foreign instanceof LinStringTag stringTag) { + return net.minecraft.nbt.StringTag.valueOf(stringTag.value()); + } else if (foreign instanceof LinEndTag) { + return net.minecraft.nbt.EndTag.INSTANCE; + } else { + throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); + } + } + + @Override + public boolean supportsWatchdog() { + return watchdog != null; + } + + @Override + public void tickWatchdog() { + watchdog.tick(); + } + + private class SpigotWatchdog implements Watchdog { + private final Field instanceField; + private final Field lastTickField; + + SpigotWatchdog() throws NoSuchFieldException { + Field instanceField = WatchdogThread.class.getDeclaredField("instance"); + instanceField.setAccessible(true); + this.instanceField = instanceField; + + Field lastTickField = WatchdogThread.class.getDeclaredField("lastTick"); + lastTickField.setAccessible(true); + this.lastTickField = lastTickField; + } + + @Override + public void tick() { + try { + WatchdogThread instance = (WatchdogThread) this.instanceField.get(null); + if ((long) lastTickField.get(instance) != 0) { + WatchdogThread.tick(); + } + } catch (IllegalAccessException e) { + logger.log(Level.WARNING, "Failed to tick watchdog", e); + } + } + } + + private static class MojangWatchdog implements Watchdog { + private final DedicatedServer server; + private final Field tickField; + + MojangWatchdog(DedicatedServer server) throws NoSuchFieldException { + this.server = server; + Field tickField = MinecraftServer.class.getDeclaredField(StaticRefraction.NEXT_TICK_TIME); + if (tickField.getType() != long.class) { + throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect"); + } + tickField.setAccessible(true); + this.tickField = tickField; + } + + @Override + public void tick() { + try { + tickField.set(server, Util.getMillis()); + } catch (IllegalAccessException ignored) { + } + } + } + + private static class NoOpWorldLoadListener implements ChunkProgressListener { + @Override + public void updateSpawnPos(ChunkPos spawnPos) { + } + + @Override + public void onStatusChange(ChunkPos pos, @org.jetbrains.annotations.Nullable ChunkStatus status) { + } + + @Override + public void start() { + } + + @Override + public void stop() { + } + + } +} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightDataConverters.java similarity index 78% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightDataConverters.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightDataConverters.java index c9d8928bb..e84ba0d4e 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightDataConverters.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightDataConverters.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -31,15 +31,19 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.mojang.datafixers.DSL.TypeReference; import com.mojang.datafixers.DataFixer; -import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.FloatTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.GsonHelper; import net.minecraft.util.StringUtil; import net.minecraft.util.datafix.DataFixers; @@ -47,6 +51,7 @@ import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.item.DyeColor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.reflect.Type; @@ -60,33 +65,37 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.UUID; -import java.util.concurrent.Executor; import java.util.stream.Collectors; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) + * *

* We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy * which is safer, faster and cleaner code. + *

+ * *

* The pre DFU code did not fail when the Source version was unknown. + *

+ * *

* This class also provides util methods for converting compounds to wrap the update call to * receive the source version in the compound + *

*/ -@SuppressWarnings({"rawtypes", "unchecked"}) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { +@SuppressWarnings({ "rawtypes", "unchecked" }) +class PaperweightDataConverters implements com.sk89q.worldedit.world.DataFixer { - //FAWE start - BinaryTag @SuppressWarnings("unchecked") @Override public T fixUp(FixType type, T original, int srcVer) { if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); + return (T) fixChunk((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); + return (T) fixBlockEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); + return (T) fixEntity((LinCompoundTag) original, srcVer); } else if (type == FixTypes.BLOCK_STATE) { return (T) fixBlockState((String) original, srcVer); } else if (type == FixTypes.ITEM_TYPE) { @@ -97,61 +106,51 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return original; } - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(originalChunk); + CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(origTileEnt); + CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(origEnt); + CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); } - //FAWE end private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update( - References.BLOCK_STATE, - dynamic, - srcVer, - DATA_VERSION - ).getValue(); + CompoundTag stateNBT = stateToNBT(blockState); + Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); + CompoundTag fixed = (CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); return nbtToState(fixed); } - private String nbtToState(net.minecraft.nbt.CompoundTag tagCompound) { + private String nbtToState(CompoundTag tagCompound) { StringBuilder sb = new StringBuilder(); sb.append(tagCompound.getString("Name")); if (tagCompound.contains("Properties", 10)) { sb.append('['); - net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties"); - sb.append(props - .getAllKeys() - .stream() - .map(k -> k + "=" + props.getString(k).replace("\"", "")) - .collect(Collectors.joining(","))); + CompoundTag props = tagCompound.getCompound("Properties"); + sb.append(props.getAllKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(","))); sb.append(']'); } return sb.toString(); } - private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { + private static CompoundTag stateToNBT(String blockState) { int propIdx = blockState.indexOf('['); - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + CompoundTag tag = new CompoundTag(); if (propIdx < 0) { tag.putString("Name", blockState); } else { tag.putString("Name", blockState.substring(0, propIdx)); - net.minecraft.nbt.CompoundTag propTag = new net.minecraft.nbt.CompoundTag(); + CompoundTag propTag = new CompoundTag(); String props = blockState.substring(propIdx + 1, blockState.length() - 1); String[] propArr = props.split(","); for (String pair : propArr) { @@ -172,8 +171,8 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } private static String fixName(String key, int srcVer, TypeReference type) { - return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, net.minecraft.nbt.StringTag.valueOf(key)), srcVer, DATA_VERSION) - .getValue().getAsString(); + return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, DATA_VERSION) + .getValue().getAsString(); } private final PaperweightAdapter adapter; @@ -213,29 +212,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { - super(dataVersion); DATA_VERSION = dataVersion; INSTANCE = this; this.adapter = adapter; registerConverters(); registerInspectors(); - } - - - // Called after fixers are built and ready for FIXING - @Override - public DataFixer buildUnoptimized() { - return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); - } - - @Override - public DataFixer buildOptimized(Executor executor) { - return buildUnoptimized(); + this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); } @SuppressWarnings("unchecked") private class WrappedDataFixer implements DataFixer { - private final DataFixer realFixer; WrappedDataFixer(DataFixer realFixer) { @@ -246,7 +232,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); if (sourceVer < LEGACY_VERSION && legacyType != null) { - net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); + CompoundTag cmp = (CompoundTag) dynamic.getValue(); int desiredVersion = Math.min(targetVer, LEGACY_VERSION); cmp = convert(legacyType, cmp, sourceVer, desiredVersion); @@ -256,12 +242,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return realFixer.update(type, dynamic, sourceVer, targetVer); } - private net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int desiredVersion - ) { + private CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer, int desiredVersion) { List converters = PaperweightDataConverters.this.converters.get(type); if (converters != null && !converters.isEmpty()) { for (DataConverter converter : converters) { @@ -286,62 +267,46 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo public Schema getSchema(int i) { return realFixer.getSchema(i); } - } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { + public static CompoundTag convert(LegacyType type, CompoundTag cmp) { return convert(type.getDFUType(), cmp); } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + public static CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer) { return convert(type.getDFUType(), cmp, sourceVer); } - public static net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { + public static CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer, int targetVer) { return convert(type.getDFUType(), cmp, sourceVer, targetVer); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { + public static CompoundTag convert(TypeReference type, CompoundTag cmp) { int i = cmp.contains("DataVersion", 99) ? cmp.getInt("DataVersion") : -1; return convert(type, cmp, i); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + public static CompoundTag convert(TypeReference type, CompoundTag cmp, int sourceVer) { return convert(type, cmp, sourceVer, DATA_VERSION); } - public static net.minecraft.nbt.CompoundTag convert( - TypeReference type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int targetVer - ) { + public static CompoundTag convert(TypeReference type, CompoundTag cmp, int sourceVer, int targetVer) { if (sourceVer >= targetVer) { return cmp; } - return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer - .update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer) - .getValue(); + return (CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); } public interface DataInspector { - - net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); - + CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer); } public interface DataConverter { int getDataVersion(); - net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); - + CompoundTag convert(CompoundTag cmp); } @@ -501,114 +466,114 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo static { final Map map = OLD_ID_TO_KEY_MAP; - map.put("EntityItem", new ResourceLocation("item")); - map.put("EntityExperienceOrb", new ResourceLocation("xp_orb")); - map.put("EntityAreaEffectCloud", new ResourceLocation("area_effect_cloud")); - map.put("EntityGuardianElder", new ResourceLocation("elder_guardian")); - map.put("EntitySkeletonWither", new ResourceLocation("wither_skeleton")); - map.put("EntitySkeletonStray", new ResourceLocation("stray")); - map.put("EntityEgg", new ResourceLocation("egg")); - map.put("EntityLeash", new ResourceLocation("leash_knot")); - map.put("EntityPainting", new ResourceLocation("painting")); - map.put("EntityTippedArrow", new ResourceLocation("arrow")); - map.put("EntitySnowball", new ResourceLocation("snowball")); - map.put("EntityLargeFireball", new ResourceLocation("fireball")); - map.put("EntitySmallFireball", new ResourceLocation("small_fireball")); - map.put("EntityEnderPearl", new ResourceLocation("ender_pearl")); - map.put("EntityEnderSignal", new ResourceLocation("eye_of_ender_signal")); - map.put("EntityPotion", new ResourceLocation("potion")); - map.put("EntityThrownExpBottle", new ResourceLocation("xp_bottle")); - map.put("EntityItemFrame", new ResourceLocation("item_frame")); - map.put("EntityWitherSkull", new ResourceLocation("wither_skull")); - map.put("EntityTNTPrimed", new ResourceLocation("tnt")); - map.put("EntityFallingBlock", new ResourceLocation("falling_block")); - map.put("EntityFireworks", new ResourceLocation("fireworks_rocket")); - map.put("EntityZombieHusk", new ResourceLocation("husk")); - map.put("EntitySpectralArrow", new ResourceLocation("spectral_arrow")); - map.put("EntityShulkerBullet", new ResourceLocation("shulker_bullet")); - map.put("EntityDragonFireball", new ResourceLocation("dragon_fireball")); - map.put("EntityZombieVillager", new ResourceLocation("zombie_villager")); - map.put("EntityHorseSkeleton", new ResourceLocation("skeleton_horse")); - map.put("EntityHorseZombie", new ResourceLocation("zombie_horse")); - map.put("EntityArmorStand", new ResourceLocation("armor_stand")); - map.put("EntityHorseDonkey", new ResourceLocation("donkey")); - map.put("EntityHorseMule", new ResourceLocation("mule")); - map.put("EntityEvokerFangs", new ResourceLocation("evocation_fangs")); - map.put("EntityEvoker", new ResourceLocation("evocation_illager")); - map.put("EntityVex", new ResourceLocation("vex")); - map.put("EntityVindicator", new ResourceLocation("vindication_illager")); - map.put("EntityIllagerIllusioner", new ResourceLocation("illusion_illager")); - map.put("EntityMinecartCommandBlock", new ResourceLocation("commandblock_minecart")); - map.put("EntityBoat", new ResourceLocation("boat")); - map.put("EntityMinecartRideable", new ResourceLocation("minecart")); - map.put("EntityMinecartChest", new ResourceLocation("chest_minecart")); - map.put("EntityMinecartFurnace", new ResourceLocation("furnace_minecart")); - map.put("EntityMinecartTNT", new ResourceLocation("tnt_minecart")); - map.put("EntityMinecartHopper", new ResourceLocation("hopper_minecart")); - map.put("EntityMinecartMobSpawner", new ResourceLocation("spawner_minecart")); - map.put("EntityCreeper", new ResourceLocation("creeper")); - map.put("EntitySkeleton", new ResourceLocation("skeleton")); - map.put("EntitySpider", new ResourceLocation("spider")); - map.put("EntityGiantZombie", new ResourceLocation("giant")); - map.put("EntityZombie", new ResourceLocation("zombie")); - map.put("EntitySlime", new ResourceLocation("slime")); - map.put("EntityGhast", new ResourceLocation("ghast")); - map.put("EntityPigZombie", new ResourceLocation("zombie_pigman")); - map.put("EntityEnderman", new ResourceLocation("enderman")); - map.put("EntityCaveSpider", new ResourceLocation("cave_spider")); - map.put("EntitySilverfish", new ResourceLocation("silverfish")); - map.put("EntityBlaze", new ResourceLocation("blaze")); - map.put("EntityMagmaCube", new ResourceLocation("magma_cube")); - map.put("EntityEnderDragon", new ResourceLocation("ender_dragon")); - map.put("EntityWither", new ResourceLocation("wither")); - map.put("EntityBat", new ResourceLocation("bat")); - map.put("EntityWitch", new ResourceLocation("witch")); - map.put("EntityEndermite", new ResourceLocation("endermite")); - map.put("EntityGuardian", new ResourceLocation("guardian")); - map.put("EntityShulker", new ResourceLocation("shulker")); - map.put("EntityPig", new ResourceLocation("pig")); - map.put("EntitySheep", new ResourceLocation("sheep")); - map.put("EntityCow", new ResourceLocation("cow")); - map.put("EntityChicken", new ResourceLocation("chicken")); - map.put("EntitySquid", new ResourceLocation("squid")); - map.put("EntityWolf", new ResourceLocation("wolf")); - map.put("EntityMushroomCow", new ResourceLocation("mooshroom")); - map.put("EntitySnowman", new ResourceLocation("snowman")); - map.put("EntityOcelot", new ResourceLocation("ocelot")); - map.put("EntityIronGolem", new ResourceLocation("villager_golem")); - map.put("EntityHorse", new ResourceLocation("horse")); - map.put("EntityRabbit", new ResourceLocation("rabbit")); - map.put("EntityPolarBear", new ResourceLocation("polar_bear")); - map.put("EntityLlama", new ResourceLocation("llama")); - map.put("EntityLlamaSpit", new ResourceLocation("llama_spit")); - map.put("EntityParrot", new ResourceLocation("parrot")); - map.put("EntityVillager", new ResourceLocation("villager")); - map.put("EntityEnderCrystal", new ResourceLocation("ender_crystal")); - map.put("TileEntityFurnace", new ResourceLocation("furnace")); - map.put("TileEntityChest", new ResourceLocation("chest")); - map.put("TileEntityEnderChest", new ResourceLocation("ender_chest")); - map.put("TileEntityRecordPlayer", new ResourceLocation("jukebox")); - map.put("TileEntityDispenser", new ResourceLocation("dispenser")); - map.put("TileEntityDropper", new ResourceLocation("dropper")); - map.put("TileEntitySign", new ResourceLocation("sign")); - map.put("TileEntityMobSpawner", new ResourceLocation("mob_spawner")); - map.put("TileEntityNote", new ResourceLocation("noteblock")); - map.put("TileEntityPiston", new ResourceLocation("piston")); - map.put("TileEntityBrewingStand", new ResourceLocation("brewing_stand")); - map.put("TileEntityEnchantTable", new ResourceLocation("enchanting_table")); - map.put("TileEntityEnderPortal", new ResourceLocation("end_portal")); - map.put("TileEntityBeacon", new ResourceLocation("beacon")); - map.put("TileEntitySkull", new ResourceLocation("skull")); - map.put("TileEntityLightDetector", new ResourceLocation("daylight_detector")); - map.put("TileEntityHopper", new ResourceLocation("hopper")); - map.put("TileEntityComparator", new ResourceLocation("comparator")); - map.put("TileEntityFlowerPot", new ResourceLocation("flower_pot")); - map.put("TileEntityBanner", new ResourceLocation("banner")); - map.put("TileEntityStructure", new ResourceLocation("structure_block")); - map.put("TileEntityEndGateway", new ResourceLocation("end_gateway")); - map.put("TileEntityCommand", new ResourceLocation("command_block")); - map.put("TileEntityShulkerBox", new ResourceLocation("shulker_box")); - map.put("TileEntityBed", new ResourceLocation("bed")); + map.put("EntityItem", ResourceLocation.parse("item")); + map.put("EntityExperienceOrb", ResourceLocation.parse("xp_orb")); + map.put("EntityAreaEffectCloud", ResourceLocation.parse("area_effect_cloud")); + map.put("EntityGuardianElder", ResourceLocation.parse("elder_guardian")); + map.put("EntitySkeletonWither", ResourceLocation.parse("wither_skeleton")); + map.put("EntitySkeletonStray", ResourceLocation.parse("stray")); + map.put("EntityEgg", ResourceLocation.parse("egg")); + map.put("EntityLeash", ResourceLocation.parse("leash_knot")); + map.put("EntityPainting", ResourceLocation.parse("painting")); + map.put("EntityTippedArrow", ResourceLocation.parse("arrow")); + map.put("EntitySnowball", ResourceLocation.parse("snowball")); + map.put("EntityLargeFireball", ResourceLocation.parse("fireball")); + map.put("EntitySmallFireball", ResourceLocation.parse("small_fireball")); + map.put("EntityEnderPearl", ResourceLocation.parse("ender_pearl")); + map.put("EntityEnderSignal", ResourceLocation.parse("eye_of_ender_signal")); + map.put("EntityPotion", ResourceLocation.parse("potion")); + map.put("EntityThrownExpBottle", ResourceLocation.parse("xp_bottle")); + map.put("EntityItemFrame", ResourceLocation.parse("item_frame")); + map.put("EntityWitherSkull", ResourceLocation.parse("wither_skull")); + map.put("EntityTNTPrimed", ResourceLocation.parse("tnt")); + map.put("EntityFallingBlock", ResourceLocation.parse("falling_block")); + map.put("EntityFireworks", ResourceLocation.parse("fireworks_rocket")); + map.put("EntityZombieHusk", ResourceLocation.parse("husk")); + map.put("EntitySpectralArrow", ResourceLocation.parse("spectral_arrow")); + map.put("EntityShulkerBullet", ResourceLocation.parse("shulker_bullet")); + map.put("EntityDragonFireball", ResourceLocation.parse("dragon_fireball")); + map.put("EntityZombieVillager", ResourceLocation.parse("zombie_villager")); + map.put("EntityHorseSkeleton", ResourceLocation.parse("skeleton_horse")); + map.put("EntityHorseZombie", ResourceLocation.parse("zombie_horse")); + map.put("EntityArmorStand", ResourceLocation.parse("armor_stand")); + map.put("EntityHorseDonkey", ResourceLocation.parse("donkey")); + map.put("EntityHorseMule", ResourceLocation.parse("mule")); + map.put("EntityEvokerFangs", ResourceLocation.parse("evocation_fangs")); + map.put("EntityEvoker", ResourceLocation.parse("evocation_illager")); + map.put("EntityVex", ResourceLocation.parse("vex")); + map.put("EntityVindicator", ResourceLocation.parse("vindication_illager")); + map.put("EntityIllagerIllusioner", ResourceLocation.parse("illusion_illager")); + map.put("EntityMinecartCommandBlock", ResourceLocation.parse("commandblock_minecart")); + map.put("EntityBoat", ResourceLocation.parse("boat")); + map.put("EntityMinecartRideable", ResourceLocation.parse("minecart")); + map.put("EntityMinecartChest", ResourceLocation.parse("chest_minecart")); + map.put("EntityMinecartFurnace", ResourceLocation.parse("furnace_minecart")); + map.put("EntityMinecartTNT", ResourceLocation.parse("tnt_minecart")); + map.put("EntityMinecartHopper", ResourceLocation.parse("hopper_minecart")); + map.put("EntityMinecartMobSpawner", ResourceLocation.parse("spawner_minecart")); + map.put("EntityCreeper", ResourceLocation.parse("creeper")); + map.put("EntitySkeleton", ResourceLocation.parse("skeleton")); + map.put("EntitySpider", ResourceLocation.parse("spider")); + map.put("EntityGiantZombie", ResourceLocation.parse("giant")); + map.put("EntityZombie", ResourceLocation.parse("zombie")); + map.put("EntitySlime", ResourceLocation.parse("slime")); + map.put("EntityGhast", ResourceLocation.parse("ghast")); + map.put("EntityPigZombie", ResourceLocation.parse("zombie_pigman")); + map.put("EntityEnderman", ResourceLocation.parse("enderman")); + map.put("EntityCaveSpider", ResourceLocation.parse("cave_spider")); + map.put("EntitySilverfish", ResourceLocation.parse("silverfish")); + map.put("EntityBlaze", ResourceLocation.parse("blaze")); + map.put("EntityMagmaCube", ResourceLocation.parse("magma_cube")); + map.put("EntityEnderDragon", ResourceLocation.parse("ender_dragon")); + map.put("EntityWither", ResourceLocation.parse("wither")); + map.put("EntityBat", ResourceLocation.parse("bat")); + map.put("EntityWitch", ResourceLocation.parse("witch")); + map.put("EntityEndermite", ResourceLocation.parse("endermite")); + map.put("EntityGuardian", ResourceLocation.parse("guardian")); + map.put("EntityShulker", ResourceLocation.parse("shulker")); + map.put("EntityPig", ResourceLocation.parse("pig")); + map.put("EntitySheep", ResourceLocation.parse("sheep")); + map.put("EntityCow", ResourceLocation.parse("cow")); + map.put("EntityChicken", ResourceLocation.parse("chicken")); + map.put("EntitySquid", ResourceLocation.parse("squid")); + map.put("EntityWolf", ResourceLocation.parse("wolf")); + map.put("EntityMushroomCow", ResourceLocation.parse("mooshroom")); + map.put("EntitySnowman", ResourceLocation.parse("snowman")); + map.put("EntityOcelot", ResourceLocation.parse("ocelot")); + map.put("EntityIronGolem", ResourceLocation.parse("villager_golem")); + map.put("EntityHorse", ResourceLocation.parse("horse")); + map.put("EntityRabbit", ResourceLocation.parse("rabbit")); + map.put("EntityPolarBear", ResourceLocation.parse("polar_bear")); + map.put("EntityLlama", ResourceLocation.parse("llama")); + map.put("EntityLlamaSpit", ResourceLocation.parse("llama_spit")); + map.put("EntityParrot", ResourceLocation.parse("parrot")); + map.put("EntityVillager", ResourceLocation.parse("villager")); + map.put("EntityEnderCrystal", ResourceLocation.parse("ender_crystal")); + map.put("TileEntityFurnace", ResourceLocation.parse("furnace")); + map.put("TileEntityChest", ResourceLocation.parse("chest")); + map.put("TileEntityEnderChest", ResourceLocation.parse("ender_chest")); + map.put("TileEntityRecordPlayer", ResourceLocation.parse("jukebox")); + map.put("TileEntityDispenser", ResourceLocation.parse("dispenser")); + map.put("TileEntityDropper", ResourceLocation.parse("dropper")); + map.put("TileEntitySign", ResourceLocation.parse("sign")); + map.put("TileEntityMobSpawner", ResourceLocation.parse("mob_spawner")); + map.put("TileEntityNote", ResourceLocation.parse("noteblock")); + map.put("TileEntityPiston", ResourceLocation.parse("piston")); + map.put("TileEntityBrewingStand", ResourceLocation.parse("brewing_stand")); + map.put("TileEntityEnchantTable", ResourceLocation.parse("enchanting_table")); + map.put("TileEntityEnderPortal", ResourceLocation.parse("end_portal")); + map.put("TileEntityBeacon", ResourceLocation.parse("beacon")); + map.put("TileEntitySkull", ResourceLocation.parse("skull")); + map.put("TileEntityLightDetector", ResourceLocation.parse("daylight_detector")); + map.put("TileEntityHopper", ResourceLocation.parse("hopper")); + map.put("TileEntityComparator", ResourceLocation.parse("comparator")); + map.put("TileEntityFlowerPot", ResourceLocation.parse("flower_pot")); + map.put("TileEntityBanner", ResourceLocation.parse("banner")); + map.put("TileEntityStructure", ResourceLocation.parse("structure_block")); + map.put("TileEntityEndGateway", ResourceLocation.parse("end_gateway")); + map.put("TileEntityCommand", ResourceLocation.parse("command_block")); + map.put("TileEntityShulkerBox", ResourceLocation.parse("shulker_box")); + map.put("TileEntityBed", ResourceLocation.parse("bed")); } private static ResourceLocation getKey(String type) { @@ -619,25 +584,19 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return key; } - private static void convertCompound( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - String key, - int sourceVer, - int targetVer - ) { + private static void convertCompound(LegacyType type, CompoundTag cmp, String key, int sourceVer, int targetVer) { cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer)); } - private static void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + private static void convertItem(CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { if (nbttagcompound.contains(key, 10)) { convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); } } - private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + private static void convertItems(CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { if (nbttagcompound.contains(key, 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound.getList(key, 10); + ListTag nbttaglist = nbttagcompound.getList(key, 10); for (int j = 0; j < nbttaglist.size(); ++j) { nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); @@ -655,19 +614,19 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 100; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Equipment", 10); - net.minecraft.nbt.ListTag nbttaglist1; + public CompoundTag convert(CompoundTag cmp) { + ListTag nbttaglist = cmp.getList("Equipment", 10); + ListTag nbttaglist1; if (!nbttaglist.isEmpty() && !cmp.contains("HandItems", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); + nbttaglist1 = new ListTag(); nbttaglist1.add(nbttaglist.get(0)); - nbttaglist1.add(new net.minecraft.nbt.CompoundTag()); + nbttaglist1.add(new CompoundTag()); cmp.put("HandItems", nbttaglist1); } if (nbttaglist.size() > 1 && !cmp.contains("ArmorItem", 10)) { - nbttaglist1 = new net.minecraft.nbt.ListTag(); + nbttaglist1 = new ListTag(); nbttaglist1.add(nbttaglist.get(1)); nbttaglist1.add(nbttaglist.get(2)); nbttaglist1.add(nbttaglist.get(3)); @@ -678,21 +637,21 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo cmp.remove("Equipment"); if (cmp.contains("DropChances", 9)) { nbttaglist1 = cmp.getList("DropChances", 5); - net.minecraft.nbt.ListTag nbttaglist2; + ListTag nbttaglist2; if (!cmp.contains("HandDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(0))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(0.0F)); + nbttaglist2 = new ListTag(); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(0))); + nbttaglist2.add(FloatTag.valueOf(0.0F)); cmp.put("HandDropChances", nbttaglist2); } if (!cmp.contains("ArmorDropChances", 10)) { - nbttaglist2 = new net.minecraft.nbt.ListTag(); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(1))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(2))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(3))); - nbttaglist2.add(net.minecraft.nbt.FloatTag.valueOf(nbttaglist1.getFloat(4))); + nbttaglist2 = new ListTag(); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(1))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(2))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(3))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(4))); cmp.put("ArmorDropChances", nbttaglist2); } @@ -701,7 +660,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorBlockEntity implements DataInspector { @@ -714,7 +672,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo @Nullable private static String convertEntityId(int i, String s) { - String key = new ResourceLocation(s).toString(); + String key = ResourceLocation.parse(s).toString(); if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { return DataInspectorBlockEntity.b.get(key); } else { @@ -722,14 +680,14 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } } - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { if (!cmp.contains("tag", 10)) { return cmp; } else { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); String s = cmp.getString("id"); String s1 = convertEntityId(sourceVer, s); boolean flag; @@ -851,11 +809,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo DataInspectorEntity() { } - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("EntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); String s = cmp.getString("id"); String s1; @@ -882,7 +840,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } @@ -894,20 +851,15 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo this.key = getKey(type); } - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (this.key.equals(new ResourceLocation(cmp.getString("id")))) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (this.key.equals(ResourceLocation.parse(cmp.getString("id")))) { cmp = this.inspectChecked(cmp, sourceVer, targetVer); } return cmp; } - abstract net.minecraft.nbt.CompoundTag inspectChecked( - net.minecraft.nbt.CompoundTag nbttagcompound, - int sourceVer, - int targetVer - ); - + abstract CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer); } private static class DataInspectorItemList extends DataInspectorTagged { @@ -919,14 +871,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo this.keys = astring; } - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { + CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String s : this.keys) { PaperweightDataConverters.convertItems(nbttagcompound, s, sourceVer, targetVer); } return nbttagcompound; } - } private static class DataInspectorItem extends DataInspectorTagged { @@ -938,14 +889,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo this.keys = astring; } - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { + CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String key : this.keys) { PaperweightDataConverters.convertItem(nbttagcompound, key, sourceVer, targetVer); } return nbttagcompound; } - } private static class DataConverterMaterialId implements DataConverter { @@ -959,7 +909,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 102; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if (cmp.contains("id", 99)) { short short0 = cmp.getShort("id"); @@ -1339,14 +1289,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 147; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("ArmorStand".equals(cmp.getString("id")) && cmp.getBoolean("Silent") && !cmp.getBoolean("Marker")) { cmp.remove("Silent"); } return cmp; } - } private static class DataConverterBanner implements DataConverter { @@ -1358,20 +1307,20 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 804; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:banner".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); if (nbttagcompound2.contains("Base", 99)) { cmp.putShort("Damage", (short) (nbttagcompound2.getShort("Base") & 15)); if (nbttagcompound1.contains("display", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); + CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); if (nbttagcompound3.contains("Lore", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); + ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0))) { return cmp; @@ -1393,7 +1342,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterPotionId implements DataConverter { @@ -1407,9 +1355,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 102; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:potion".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); short short0 = cmp.getShort("Damage"); if (!nbttagcompound1.contains("Potion", 8)) { @@ -1573,10 +1521,10 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 105; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); short short0 = cmp.getShort("Damage"); if (!nbttagcompound2.contains("id", 8)) { @@ -1671,15 +1619,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo private static class DataConverterMinecart implements DataConverter { - private static final List a = Lists.newArrayList( - "MinecartRideable", - "MinecartChest", - "MinecartFurnace", - "MinecartTNT", - "MinecartSpawner", - "MinecartHopper", - "MinecartCommandBlock" - ); + private static final List a = Lists.newArrayList("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock"); DataConverterMinecart() { } @@ -1688,7 +1628,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 106; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("Minecart".equals(cmp.getString("id"))) { String s = "MinecartRideable"; int i = cmp.getInt("Type"); @@ -1703,7 +1643,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterMobSpawner implements DataConverter { @@ -1715,13 +1654,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 107; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if (!"MobSpawner".equals(cmp.getString("id"))) { return cmp; } else { if (cmp.contains("EntityId", 8)) { String s = cmp.getString("EntityId"); - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); + CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); cmp.put("SpawnData", nbttagcompound1); @@ -1729,13 +1668,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); for (int i = 0; i < nbttaglist.size(); ++i) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); + CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); if (nbttagcompound2.contains("Type", 8)) { - net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); + CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); nbttagcompound3.putString("id", nbttagcompound2.getString("Type")); nbttagcompound2.put("Entity", nbttagcompound3); @@ -1748,7 +1687,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } } - } private static class DataConverterUUID implements DataConverter { @@ -1760,54 +1698,18 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 108; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if (cmp.contains("UUID", 8)) { cmp.putUUID("UUID", UUID.fromString(cmp.getString("UUID"))); } return cmp; } - } private static class DataConverterHealth implements DataConverter { - private static final Set a = Sets.newHashSet( - "ArmorStand", - "Bat", - "Blaze", - "CaveSpider", - "Chicken", - "Cow", - "Creeper", - "EnderDragon", - "Enderman", - "Endermite", - "EntityHorse", - "Ghast", - "Giant", - "Guardian", - "LavaSlime", - "MushroomCow", - "Ozelot", - "Pig", - "PigZombie", - "Rabbit", - "Sheep", - "Shulker", - "Silverfish", - "Skeleton", - "Slime", - "SnowMan", - "Spider", - "Squid", - "Villager", - "VillagerGolem", - "Witch", - "WitherBoss", - "Wolf", - "Zombie" - ); + private static final Set a = Sets.newHashSet("ArmorStand", "Bat", "Blaze", "CaveSpider", "Chicken", "Cow", "Creeper", "EnderDragon", "Enderman", "Endermite", "EntityHorse", "Ghast", "Giant", "Guardian", "LavaSlime", "MushroomCow", "Ozelot", "Pig", "PigZombie", "Rabbit", "Sheep", "Shulker", "Silverfish", "Skeleton", "Slime", "SnowMan", "Spider", "Squid", "Villager", "VillagerGolem", "Witch", "WitherBoss", "Wolf", "Zombie"); DataConverterHealth() { } @@ -1816,7 +1718,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 109; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if (DataConverterHealth.a.contains(cmp.getString("id"))) { float f; @@ -1836,7 +1738,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterSaddle implements DataConverter { @@ -1848,9 +1749,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 110; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("EntityHorse".equals(cmp.getString("id")) && !cmp.contains("SaddleItem", 10) && cmp.getBoolean("Saddle")) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = new net.minecraft.nbt.CompoundTag(); + CompoundTag nbttagcompound1 = new CompoundTag(); nbttagcompound1.putString("id", "minecraft:saddle"); nbttagcompound1.putByte("Count", (byte) 1); @@ -1861,7 +1762,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterHanging implements DataConverter { @@ -1873,7 +1773,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 111; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { String s = cmp.getString("id"); boolean flag = "Painting".equals(s); boolean flag1 = "ItemFrame".equals(s); @@ -1900,7 +1800,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterDropChances implements DataConverter { @@ -1912,8 +1811,8 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 113; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - net.minecraft.nbt.ListTag nbttaglist; + public CompoundTag convert(CompoundTag cmp) { + ListTag nbttaglist; if (cmp.contains("HandDropChances", 9)) { nbttaglist = cmp.getList("HandDropChances", 5); @@ -1924,15 +1823,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (cmp.contains("ArmorDropChances", 9)) { nbttaglist = cmp.getList("ArmorDropChances", 5); - if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat( - 2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { + if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { cmp.remove("ArmorDropChances"); } } return cmp; } - } private static class DataConverterRiding implements DataConverter { @@ -1944,9 +1841,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 135; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { while (cmp.contains("Riding", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = this.b(cmp); + CompoundTag nbttagcompound1 = this.b(cmp); this.convert(cmp, nbttagcompound1); cmp = nbttagcompound1; @@ -1955,20 +1852,19 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - protected void convert(net.minecraft.nbt.CompoundTag nbttagcompound, net.minecraft.nbt.CompoundTag nbttagcompound1) { - net.minecraft.nbt.ListTag nbttaglist = new net.minecraft.nbt.ListTag(); + protected void convert(CompoundTag nbttagcompound, CompoundTag nbttagcompound1) { + ListTag nbttaglist = new ListTag(); nbttaglist.add(nbttagcompound); nbttagcompound1.put("Passengers", nbttaglist); } - protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagcompound) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); + protected CompoundTag b(CompoundTag nbttagcompound) { + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); nbttagcompound.remove("Riding"); return nbttagcompound1; } - } private static class DataConverterBook implements DataConverter { @@ -1980,12 +1876,12 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 165; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:written_book".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("pages", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("pages", 8); + ListTag nbttaglist = nbttagcompound1.getList("pages", 8); for (int i = 0; i < nbttaglist.size(); ++i) { String s = nbttaglist.getString(i); @@ -2000,20 +1896,23 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { object = Component.literal(""); } - } catch (JsonParseException ignored) { + } catch (JsonParseException jsonparseexception) { + ; } if (object == null) { try { - object = Component.Serializer.fromJson(s); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJson(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; } } if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJsonLenient(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; } } @@ -2025,7 +1924,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo object = Component.literal(""); } - nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); + nbttaglist.set(i, StringTag.valueOf(Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess()))); } nbttagcompound1.put("pages", nbttaglist); @@ -2034,12 +1933,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterCookedFish implements DataConverter { - private static final ResourceLocation a = new ResourceLocation("cooked_fished"); + private static final ResourceLocation a = ResourceLocation.parse("cooked_fished"); DataConverterCookedFish() { } @@ -2048,14 +1946,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 502; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(new ResourceLocation(cmp.getString("id")))) { + public CompoundTag convert(CompoundTag cmp) { + if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(ResourceLocation.parse(cmp.getString("id")))) { cmp.putString("id", "minecraft:cooked_fish"); } return cmp; } - } private static class DataConverterZombie implements DataConverter { @@ -2069,7 +1966,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 502; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("Zombie".equals(cmp.getString("id")) && cmp.getBoolean("IsVillager")) { if (!cmp.contains("ZombieType", 99)) { int i = -1; @@ -2098,7 +1995,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo private int convert(int i) { return i >= 0 && i < 6 ? i : -1; } - } private static class DataConverterVBO implements DataConverter { @@ -2110,11 +2006,10 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 505; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { cmp.putString("useVbo", "true"); return cmp; } - } private static class DataConverterGuardian implements DataConverter { @@ -2126,7 +2021,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 700; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("Guardian".equals(cmp.getString("id"))) { if (cmp.getBoolean("Elder")) { cmp.putString("id", "ElderGuardian"); @@ -2137,7 +2032,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterSkeleton implements DataConverter { @@ -2149,7 +2043,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 701; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { String s = cmp.getString("id"); if ("Skeleton".equals(s)) { @@ -2166,7 +2060,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterZombieType implements DataConverter { @@ -2178,7 +2071,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 702; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("Zombie".equals(cmp.getString("id"))) { int i = cmp.getInt("ZombieType"); @@ -2205,7 +2098,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterHorse implements DataConverter { @@ -2217,7 +2109,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 703; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("EntityHorse".equals(cmp.getString("id"))) { int i = cmp.getInt("Type"); @@ -2248,7 +2140,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterTileEntity implements DataConverter { @@ -2262,7 +2153,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 704; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { String s = DataConverterTileEntity.a.get(cmp.getString("id")); if (s != null) { @@ -2310,7 +2201,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 704; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { String s = DataConverterEntity.a.get(cmp.getString("id")); if (s != null) { @@ -2408,12 +2299,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 806; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { String s = cmp.getString("id"); - if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals( - s)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(s)) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (!nbttagcompound1.contains("Potion", 8)) { nbttagcompound1.putString("Potion", "minecraft:water"); @@ -2426,7 +2316,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterShulker implements DataConverter { @@ -2438,19 +2327,18 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 808; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:shulker".equals(cmp.getString("id")) && !cmp.contains("Color", 99)) { cmp.putByte("Color", (byte) 10); } return cmp; } - } private static class DataConverterShulkerBoxItem implements DataConverter { - public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"}; + public static final String[] a = new String[] { "minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box" }; DataConverterShulkerBoxItem() { } @@ -2459,12 +2347,12 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 813; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:shulker_box".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); if (nbttagcompound2.getList("Items", 10).isEmpty()) { nbttagcompound2.remove("Items"); @@ -2487,7 +2375,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterShulkerBoxBlock implements DataConverter { @@ -2499,14 +2386,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 813; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:shulker".equals(cmp.getString("id"))) { cmp.remove("Color"); } return cmp; } - } private static class DataConverterLang implements DataConverter { @@ -2518,14 +2404,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 816; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if (cmp.contains("lang", 8)) { cmp.putString("lang", cmp.getString("lang").toLowerCase(Locale.ROOT)); } return cmp; } - } private static class DataConverterTotem implements DataConverter { @@ -2537,14 +2422,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 820; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:totem".equals(cmp.getString("id"))) { cmp.putString("id", "minecraft:totem_of_undying"); } return cmp; } - } private static class DataConverterBedBlock implements DataConverter { @@ -2558,16 +2442,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 1125; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { try { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); + CompoundTag nbttagcompound1 = cmp.getCompound("Level"); int i = nbttagcompound1.getInt("xPos"); int j = nbttagcompound1.getInt("zPos"); - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("TileEntities", 10); - net.minecraft.nbt.ListTag nbttaglist1 = nbttagcompound1.getList("Sections", 10); + ListTag nbttaglist = nbttagcompound1.getList("TileEntities", 10); + ListTag nbttaglist1 = nbttagcompound1.getList("Sections", 10); for (int k = 0; k < nbttaglist1.size(); ++k) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); + CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); byte b0 = nbttagcompound2.getByte("Y"); byte[] abyte = nbttagcompound2.getByteArray("Blocks"); @@ -2576,7 +2460,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo int i1 = l & 15; int j1 = l >> 8 & 15; int k1 = l >> 4 & 15; - net.minecraft.nbt.CompoundTag nbttagcompound3 = new net.minecraft.nbt.CompoundTag(); + CompoundTag nbttagcompound3 = new CompoundTag(); nbttagcompound3.putString("id", "bed"); nbttagcompound3.putInt("x", i1 + (i << 4)); @@ -2592,7 +2476,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataConverterBedItem implements DataConverter { @@ -2604,33 +2487,29 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 1125; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("minecraft:bed".equals(cmp.getString("id")) && cmp.getShort("Damage") == 0) { cmp.putShort("Damage", (short) DyeColor.RED.getId()); } return cmp; } - } private static class DataConverterSignText implements DataConverter { public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { - MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws - JsonParseException { + MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { if (jsonelement.isJsonPrimitive()) { return Component.literal(jsonelement.getAsString()); } else if (jsonelement.isJsonArray()) { JsonArray jsonarray = jsonelement.getAsJsonArray(); MutableComponent ichatbasecomponent = null; + Iterator iterator = jsonarray.iterator(); - for (final JsonElement jsonelement1 : jsonarray) { - MutableComponent ichatbasecomponent1 = this.a( - jsonelement1, - jsonelement1.getClass(), - jsondeserializationcontext - ); + while (iterator.hasNext()) { + JsonElement jsonelement1 = (JsonElement) iterator.next(); + MutableComponent ichatbasecomponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); if (ichatbasecomponent == null) { ichatbasecomponent = ichatbasecomponent1; @@ -2645,11 +2524,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo } } - public Object deserialize( - JsonElement jsonelement, - Type type, - JsonDeserializationContext jsondeserializationcontext - ) throws JsonParseException { + public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { return this.a(jsonelement, type, jsondeserializationcontext); } }).create(); @@ -2661,7 +2536,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return 101; } - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + public CompoundTag convert(CompoundTag cmp) { if ("Sign".equals(cmp.getString("id"))) { this.convert(cmp, "Text1"); this.convert(cmp, "Text2"); @@ -2672,7 +2547,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { + private void convert(CompoundTag nbttagcompound, String s) { String s1 = nbttagcompound.getString(s); Component object = null; @@ -2685,20 +2560,23 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo if (object == null) { object = Component.literal(""); } - } catch (JsonParseException ignored) { + } catch (JsonParseException jsonparseexception) { + ; } if (object == null) { try { - object = Component.Serializer.fromJson(s1); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJson(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; } } if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s1); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJsonLenient(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; } } @@ -2710,17 +2588,15 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo object = Component.literal(""); } - nbttagcompound.putString(s, Component.Serializer.toJson(object)); + nbttagcompound.putString(s, Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess())); } - } private static class DataInspectorPlayerVehicle implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("RootVehicle", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); + CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); if (nbttagcompound1.contains("Entity", 10)) { convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); @@ -2729,35 +2605,31 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorLevelPlayer implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("Player", 10)) { convertCompound(LegacyType.PLAYER, cmp, "Player", sourceVer, targetVer); } return cmp; } - } private static class DataInspectorStructure implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.ListTag nbttaglist; + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + ListTag nbttaglist; int j; - net.minecraft.nbt.CompoundTag nbttagcompound1; + CompoundTag nbttagcompound1; if (cmp.contains("entities", 9)) { nbttaglist = cmp.getList("entities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); + nbttagcompound1 = (CompoundTag) nbttaglist.get(j); if (nbttagcompound1.contains("nbt", 10)) { convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); } @@ -2768,7 +2640,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo nbttaglist = cmp.getList("blocks", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); + nbttagcompound1 = (CompoundTag) nbttaglist.get(j); if (nbttagcompound1.contains("nbt", 10)) { convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); } @@ -2777,31 +2649,21 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorChunks implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("Level", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); - net.minecraft.nbt.ListTag nbttaglist; + CompoundTag nbttagcompound1 = cmp.getCompound("Level"); + ListTag nbttaglist; int j; if (nbttagcompound1.contains("Entities", 9)) { nbttaglist = nbttagcompound1.getList("Entities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert( - LegacyType.ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); + nbttaglist.set(j, convert(LegacyType.ENTITY, (CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); } } @@ -2809,30 +2671,20 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo nbttaglist = nbttagcompound1.getList("TileEntities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert( - LegacyType.BLOCK_ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); + nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); } } } return cmp; } - } private static class DataInspectorEntityPassengers implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("Passengers", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("Passengers", 10); + ListTag nbttaglist = cmp.getList("Passengers", 10); for (int j = 0; j < nbttaglist.size(); ++j) { nbttaglist.set(j, convert(LegacyType.ENTITY, nbttaglist.getCompound(j), sourceVer, targetVer)); @@ -2841,13 +2693,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorPlayer implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { convertItems(cmp, "Inventory", sourceVer, targetVer); convertItems(cmp, "EnderItems", sourceVer, targetVer); if (cmp.contains("ShoulderEntityLeft", 10)) { @@ -2860,23 +2710,21 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorVillagers implements DataInspector { - ResourceLocation entityVillager = getKey("EntityVillager"); @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (entityVillager.equals(new ResourceLocation(cmp.getString("id"))) && cmp.contains("Offers", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Offers"); + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (entityVillager.equals(ResourceLocation.parse(cmp.getString("id"))) && cmp.contains("Offers", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("Offers"); if (nbttagcompound1.contains("Recipes", 9)) { - net.minecraft.nbt.ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); + ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); + CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); convertItem(nbttagcompound2, "buy", sourceVer, targetVer); convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); @@ -2888,18 +2736,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorMobSpawnerMinecart implements DataInspector { - ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { String s = cmp.getString("id"); - if (entityMinecartMobSpawner.equals(new ResourceLocation(s))) { + if (entityMinecartMobSpawner.equals(ResourceLocation.parse(s))) { cmp.putString("id", tileEntityMobSpawner.toString()); convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); cmp.putString("id", s); @@ -2907,21 +2753,19 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorMobSpawnerMobs implements DataInspector { - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityMobSpawner.equals(new ResourceLocation(cmp.getString("id")))) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (tileEntityMobSpawner.equals(ResourceLocation.parse(cmp.getString("id")))) { if (cmp.contains("SpawnPotentials", 9)) { - net.minecraft.nbt.ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); + CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); } @@ -2932,16 +2776,14 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } private static class DataInspectorCommandBlock implements DataInspector { - ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (tileEntityCommand.equals(new ResourceLocation(cmp.getString("id")))) { + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (tileEntityCommand.equals(ResourceLocation.parse(cmp.getString("id")))) { cmp.putString("id", "Control"); convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); cmp.putString("id", "MinecartCommandBlock"); @@ -2949,7 +2791,5 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo return cmp; } - } - } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightFakePlayer.java similarity index 77% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightFakePlayer.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightFakePlayer.java index 43964319c..d9c89b0e3 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightFakePlayer.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightFakePlayer.java @@ -17,35 +17,33 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1; import com.mojang.authlib.GameProfile; -import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import java.util.OptionalInt; import java.util.UUID; class PaperweightFakePlayer extends ServerPlayer { - - private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( - UUID.nameUUIDFromBytes("worldedit".getBytes()), - "[WorldEdit]" - ); + private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false + ); PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, null); + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } @Override @@ -61,18 +59,13 @@ class PaperweightFakePlayer extends ServerPlayer { public void die(DamageSource damagesource) { } - @Override - public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) { - return this; - } - @Override public OptionalInt openMenu(MenuProvider factory) { return OptionalInt.empty(); } @Override - public void updateOptions(ServerboundClientInformationPacket packet) { + public void updateOptions(ClientInformation clientOptions) { } @Override @@ -93,7 +86,6 @@ class PaperweightFakePlayer extends ServerPlayer { } @Override - public void openTextEdit(SignBlockEntity sign) { + public void openTextEdit(SignBlockEntity sign, boolean front) { } - } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightWorldNativeAccess.java similarity index 68% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightWorldNativeAccess.java index 3f748bb9d..d51295053 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R1/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightWorldNativeAccess.java @@ -17,31 +17,31 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; -public class PaperweightWorldNativeAccess implements - WorldNativeAccess { - +public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; private static final int NOTIFY = 2; @@ -72,8 +72,8 @@ public class PaperweightWorldNativeAccess implements public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) { int stateId = BlockStateIdAccess.getBlockStateId(state); return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); + ? Block.stateById(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); } @Override @@ -83,19 +83,12 @@ public class PaperweightWorldNativeAccess implements @Nullable @Override - public net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState state - ) { + public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) { return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); } @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState block, - BlockPos position - ) { + public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) { return Block.updateFromNeighbourShapes(block, getWorld(), position); } @@ -110,17 +103,19 @@ public class PaperweightWorldNativeAccess implements } @Override - public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) { - return false; + public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) { + // We will assume that the tile entity was created for us + BlockEntity tileEntity = getWorld().getBlockEntity(position); + if (tileEntity == null) { + return false; + } + Tag nativeTag = adapter.fromNativeLin(tag); + PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity); + return true; } @Override - public void notifyBlockUpdate( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); } @@ -128,7 +123,7 @@ public class PaperweightWorldNativeAccess implements @Override public boolean isChunkTicking(LevelChunk chunk) { - return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); } @Override @@ -139,11 +134,7 @@ public class PaperweightWorldNativeAccess implements } @Override - public void notifyNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { ServerLevel world = getWorld(); if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { world.updateNeighborsAt(pos, oldState.getBlock()); @@ -162,28 +153,23 @@ public class PaperweightWorldNativeAccess implements } } - @SuppressWarnings("deprecation") + @Override + public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + ServerLevel world = getWorld(); + newState.onPlace(world, pos, oldState, false); + } + private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { - world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false); + world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false); } @Override - public void updateNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { + public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) { ServerLevel world = getWorld(); - // a == updateNeighbors - // b == updateDiagonalNeighbors oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { CraftWorld craftWorld = world.getWorld(); - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), - CraftBlockData.fromData(newState) - ); + BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState)); world.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; @@ -194,11 +180,7 @@ public class PaperweightWorldNativeAccess implements } @Override - public void onBlockStateChange( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { getWorld().onBlockStateChange(pos, oldState, newState); } @@ -206,5 +188,4 @@ public class PaperweightWorldNativeAccess implements public void flush() { } - } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/StaticRefraction.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/StaticRefraction.java new file mode 100644 index 000000000..5056a7981 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/StaticRefraction.java @@ -0,0 +1,90 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1; + +import com.sk89q.worldedit.bukkit.adapter.Refraction; + +/** + * Dedicated class to map all names that we use. + * + *

+ * Overloads are split into multiple fields, as they CAN have different obfuscated names. + *

+ */ +public final class StaticRefraction { + public static final String GET_CHUNK_FUTURE_MAIN_THREAD = Refraction.pickName( + "getChunkFutureMainThread", "c" + ); + public static final String MAIN_THREAD_PROCESSOR = Refraction.pickName( + "mainThreadProcessor", "g" + ); + public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e"); + public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_"); + /** + * {@code addFreshEntityWithPassengers(Entity entity)}. + */ + public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY = Refraction.pickName( + "addFreshEntityWithPassengers", "a_" + ); + /** + * {@code addFreshEntityWithPassengers(Entity entity, CreatureSpawnEvent.SpawnReason reason)}. + */ + public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY_SPAWN_REASON = + Refraction.pickName("addFreshEntityWithPassengers", "a_"); + /** + * {@code addFreshEntity(Entity entity)}. + */ + public static final String ADD_FRESH_ENTITY = Refraction.pickName("addFreshEntity", "b"); + /** + * {@code addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason)}. + */ + public static final String ADD_FRESH_ENTITY_SPAWN_REASON = Refraction.pickName( + "addFreshEntity", "b" + ); + /** + * {@code getBlockEntity(BlockPos blockPos)}. + */ + public static final String GET_BLOCK_ENTITY = Refraction.pickName("getBlockEntity", "c_"); + /** + * {@code setBlock(BlockPos blockPos, BlockState blockState, int flags)}. + */ + public static final String SET_BLOCK = Refraction.pickName("setBlock", "a"); + /** + * {@code setBlock(BlockPos blockPos, BlockState blockState, int flags, int maxUpdateDepth)}. + */ + public static final String SET_BLOCK_MAX_UPDATE = Refraction.pickName("setBlock", "a"); + public static final String REMOVE_BLOCK = Refraction.pickName("removeBlock", "a"); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop)}. + */ + public static final String DESTROY_BLOCK = Refraction.pickName("destroyBlock", "b"); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity)}. + */ + public static final String DESTROY_BLOCK_BREAKING_ENTITY = Refraction.pickName( + "destroyBlock", "a" + ); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity, int maxUpdateDepth)}. + */ + public static final String DESTROY_BLOCK_BREAKING_ENTITY_MAX_UPDATE = Refraction.pickName( + "destroyBlock", "a" + ); +} diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java similarity index 67% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java index b5da62e0f..d48e5fe1d 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java @@ -1,32 +1,27 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.util.ReflectionUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.PushReaction; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.block.data.CraftBlockData; + +import javax.annotation.Nullable; public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; private final BlockState blockState; - private final Material material; - private final boolean isTranslucent; private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; - private final CompoundTag tile; + private final FaweCompoundTag tile; public PaperweightBlockMaterial(Block block) { this(block, block.defaultBlockState()); @@ -35,14 +30,8 @@ public class PaperweightBlockMaterial implements BlockMaterial { public PaperweightBlockMaterial(Block block, BlockState blockState) { this.block = block; this.blockState = blockState; - this.material = blockState.getMaterial(); this.craftBlockData = CraftBlockData.fromData(blockState); this.craftMaterial = craftBlockData.getMaterial(); - BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName( - "properties", "aO")); - this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo, - Refraction.pickName("canOcclude", "n") - ); opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( BlockPos.ZERO, @@ -50,7 +39,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { ); tile = tileEntity == null ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); } public Block getBlock() { @@ -65,10 +54,6 @@ public class PaperweightBlockMaterial implements BlockMaterial { return craftBlockData; } - public Material getMaterial() { - return material; - } - @Override public boolean isAir() { return blockState.isAir(); @@ -81,7 +66,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isOpaque() { - return material.isSolidBlocking(); + return blockState.canOcclude(); } @Override @@ -91,12 +76,13 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isLiquid() { - return material.isLiquid(); + return !blockState.getFluidState().is(Fluids.EMPTY); } @Override public boolean isSolid() { - return material.isSolid(); + // No access to world -> EmptyBlockGetter + return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); } @Override @@ -126,27 +112,28 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; + return blockState.getPistonPushReaction() == PushReaction.DESTROY; } @Override public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; + return blockState.getPistonPushReaction() == PushReaction.BLOCK; } @Override public boolean isTicksRandomly() { - return block.isRandomlyTicking(blockState); + return blockState.isRandomlyTicking(); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return material.isSolid(); + return blockState.blocksMotion(); } @Override public boolean isBurnable() { - return material.isFlammable(); + return craftMaterial.isBurnable(); } @Override @@ -157,12 +144,12 @@ public class PaperweightBlockMaterial implements BlockMaterial { @Override public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); + return blockState.canBeReplaced(); } @Override public boolean isTranslucent() { - return isTranslucent; + return !blockState.canOcclude(); } @Override @@ -176,14 +163,14 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } @Override public int getMapColor() { // rgb field - return material.getColor().col; + return block.defaultMapColor().col; } } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java index b9aa9cf7f..353f6b5c1 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java @@ -1,29 +1,25 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; -import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; -import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter; +import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.NbtUtils; -import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Codec; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.regen.PaperweightRegen; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.regen.PaperweightRegen; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -39,18 +35,14 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemType; @@ -58,42 +50,45 @@ import com.sk89q.worldedit.world.registry.BlockMaterial; import io.papermc.lib.PaperLib; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; -import net.minecraft.nbt.IntTag; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.StringRepresentable; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.TreeType; +import org.bukkit.World; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_19_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_19_R1.CraftServer; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockState; -import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_19_R1.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.entity.Player; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -109,15 +104,20 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; -public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements - IDelegateBukkitImplAdapter { +import static net.minecraft.core.registries.Registries.BIOME; + +public final class PaperweightFaweAdapter extends FaweAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); static { try { @@ -126,18 +126,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } } - private final PaperweightAdapter parent; - // ------------------------------------------------------------------------ - // Code that may break between versions of Minecraft - // ------------------------------------------------------------------------ private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); - private char[] ibdToStateOrdinal = null; - private int[] ordinalToIbdID = null; - private boolean initialised = false; - private Map>> allBlockProperties = null; public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); + super(new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1.PaperweightAdapter()); + } + + public Function blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); } @Nullable @@ -241,7 +239,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } public Block getBlock(BlockType blockType) { - return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK) + .get(ResourceLocation.fromNamespaceAndPath(blockType.getNamespace(), blockType.getResource())); } @Deprecated @@ -249,11 +248,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BlockState getBlock(Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -269,12 +267,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public BaseBlock getFullBlock(final Location location) { Preconditions.checkNotNull(location); - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); int x = location.getBlockX(); int y = location.getBlockY(); int z = location.getBlockZ(); - final ServerLevel handle = craftWorld.getHandle(); + final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); @@ -288,8 +285,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements // Read the NBT data BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()); + return state.toBaseBlock((LinCompoundTag) toNativeLin(tag)); } } @@ -301,60 +298,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements return SideEffectSet.defaults().getSideEffectsToApply(); } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { - CraftChunk craftChunk = (CraftChunk) chunk; - LevelChunk levelChunk = craftChunk.getHandle(); - Level level = levelChunk.getLevel(); - - BlockPos blockPos = new BlockPos(x, y, z); - net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - LevelChunkSection[] levelChunkSections = levelChunk.getSections(); - int y4 = y >> 4; - LevelChunkSection section = levelChunkSections[y4]; - - net.minecraft.world.level.block.state.BlockState existing; - if (section == null) { - existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); - } else { - existing = section.getBlockState(x & 15, y & 15, z & 15); - } - - levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity - - CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null; - if (compoundTag != null || existing instanceof TileEntityBlock) { - level.setBlock(blockPos, blockState, 0); - // remove tile - if (compoundTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - BlockEntity blockEntity = level.getBlockEntity(blockPos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - blockEntity.load(tag); // readTagIntoTileEntity - load data - } - } - } else { - if (existing == blockState) { - return true; - } - levelChunk.setBlockState(blockPos, blockState, false); - } - if (update) { - level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0); - } - return true; - } - @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightFaweWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); + return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); } @Override @@ -368,14 +314,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements if (id != null) { EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); - Supplier saveTag = () -> { + Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work - final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); - final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); - tags.put("Id", StringBinaryTag.of(id)); - return CompoundBinaryTag.from(tags); + final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag); + final Map> tags = NbtUtils.getLinCompoundTagValues(tag); + tags.put("Id", LinStringTag.of(id)); + return LinCompoundTag.of(tags); }; return new LazyBaseEntity(type, saveTag); } else { @@ -499,7 +445,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements @Override public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { - ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); + ServerLevel nmsWorld = getServerLevel(world); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); if (map != null && wasAccessibleSinceLastSave(map)) { boolean flag = false; @@ -537,71 +483,64 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements int internalId = BlockStateIdAccess.getBlockStateId(blockState); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); return blockState1.hasPostProcess( - ((CraftWorld) world).getHandle(), - new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) + getServerLevel(world), + new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z()) ); } @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); ItemStack stack = new ItemStack( - Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())), baseItemStack.getAmount() ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()); + if (nbt != null) { + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); + } return CraftItemStack.asCraftMirror(stack); } @Override - public boolean generateTree( - TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, - org.bukkit.World bukkitWorld - ) { - TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); - if (bukkitType == TreeType.CHORUS_PLANT) { - blockVector3 = blockVector3.add( - 0, - 1, - 0 - ); // bukkit skips the feature gen which does this offset normally, so we have to add it back - } - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - final BlockVector3 finalBlockVector = blockVector3; - // Sync to main thread to ensure no clashes occur - Map placed = TaskManager.taskManager().sync(() -> { - serverLevel.captureTreeGeneration = true; - serverLevel.captureBlockStates = true; - try { - if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { - return null; - } - return ImmutableMap.copyOf(serverLevel.capturedBlockStates); - } finally { - serverLevel.captureBlockStates = false; - serverLevel.captureTreeGeneration = false; - serverLevel.capturedBlockStates.clear(); - } - }); - if (placed == null || placed.isEmpty()) { - return false; - } - for (CraftBlockState craftBlockState : placed.values()) { - if (craftBlockState == null || craftBlockState.getType() == Material.AIR) { - continue; - } - editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(), - BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData()) - ); - } - return true; + protected void preCaptureStates(final ServerLevel serverLevel) { + serverLevel.captureTreeGeneration = true; + serverLevel.captureBlockStates = true; + } + + @Override + protected List getCapturedBlockStatesCopy(final ServerLevel serverLevel) { + return new ArrayList<>(serverLevel.capturedBlockStates.values()); + } + + @Override + protected void postCaptureBlockStates(final ServerLevel serverLevel) { + serverLevel.captureBlockStates = false; + serverLevel.captureTreeGeneration = false; + serverLevel.capturedBlockStates.clear(); + } + + @Override + protected ServerLevel getServerLevel(final World world) { + return ((CraftWorld) world).getHandle(); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; + final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), + itemStack.getAmount() + ); } @Override @@ -632,8 +571,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements final Registry registry = MinecraftServer .getServer() .registryAccess() - .ownedRegistryOrThrow(Registry.BIOME_REGISTRY); - ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); + .registryOrThrow(BIOME); + ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id()); Biome biome = registry.get(resourceLocation); return registry.getId(biome); } @@ -643,8 +582,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements WritableRegistry biomeRegistry = (WritableRegistry) ((CraftServer) Bukkit.getServer()) .getServer() .registryAccess() - .ownedRegistryOrThrow( - Registry.BIOME_REGISTRY); + .registryOrThrow(BIOME); List keys = biomeRegistry.stream() .map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); List namespacedKeys = new ArrayList<>(); @@ -687,15 +625,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements } private boolean wasAccessibleSinceLastSave(ChunkHolder holder) { - if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) { - try { - return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder); - } catch (IllegalAccessException | InvocationTargetException ignored) { - // fall-through - } + if (PaperLib.isPaper()) { // Papers new chunk system has no related replacement - therefor we assume true. + return true; + } + try { + return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder); + } catch (IllegalAccessException | InvocationTargetException ignored) { + return false; } - // Papers new chunk system has no related replacement - therefor we assume true. - return true; } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweWorldNativeAccess.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweWorldNativeAccess.java index e5c26aba5..f7c2dc8e8 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweWorldNativeAccess.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; @@ -9,21 +9,22 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.lang.ref.WeakReference; @@ -102,7 +103,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess currentTick; if (nextTick || cachedChanges.size() >= 1024) { if (nextTick) { @@ -132,15 +133,15 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; + private final IntPair chunkPos; private final int minHeight; private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -109,6 +143,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc this.blockLight = new DataLayer[getSectionCount()]; this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); } public int getChunkX() { @@ -125,13 +160,28 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + // Increment regardless of whether copy will be created or not to return null from getCopy() + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -215,23 +265,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -294,14 +345,22 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + public @Nullable FaweCompoundTag entity(final UUID uuid) { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -309,14 +368,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -329,10 +388,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -344,15 +403,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { + CompoundTag tag = new CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; + } private void removeEntity(Entity entity) { @@ -366,12 +426,19 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - // Remove existing tiles. Create a copy so that we can remove blocks Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -443,6 +510,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -460,7 +529,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } } } else { - setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes()); + PalettedContainer> paletteBiomes = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + if (paletteBiomes != null) { + PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes); + } } } } @@ -484,9 +560,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc // Don't attempt to tick section whilst we're editing if (existingSection != null) { PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } } if (createCopy) { @@ -502,11 +575,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (existingSection == null) { PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( biomeHolderIdMap, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId( - BiomeTypes.PLAINS)), + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), PalettedContainer.Strategy.SECTION_BIOMES ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); newSection = PaperweightPlatformAdapter.newChunkSection( @@ -517,6 +586,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -537,9 +608,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc //ensure that the server doesn't try to tick the chunksection while we're editing it. (Again) PaperweightPlatformAdapter.clearCounts(existingSection); - if (PaperLib.isPaper()) { - existingSection.tickingList.clear(); - } DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection); // Synchronize to prevent further acquisitions @@ -573,16 +641,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc existingSection.getBiomes() ); - newSection = - PaperweightPlatformAdapter.newChunkSection( - layerNo, - this::loadPrivately, - setArr, - adapter, - biomeRegistry, - biomeData - ); + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + this::loadPrivately, + setArr, + adapter, + biomeRegistry, + biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() + ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -656,7 +725,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -668,48 +737,47 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + entity.setUUID(NbtUtils.uuid(nativeTag)); + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -724,34 +792,33 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); - final int x = blockHash.getX() + bx; - final int y = blockHash.getY(); - final int z = blockHash.getZ() + bz; + final int x = blockHash.x() + bx; + final int y = blockHash.y(); + final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); - tileEntity.load(tag); + tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess()); } } } @@ -763,15 +830,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified nmsChunk.mustNotSave = false; nmsChunk.setUnsaved(true); // send to player - if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { - this.send(finalMask, finalLightUpdate); + if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) { + this.send(); } if (finalizer != null) { finalizer.run(); @@ -793,7 +859,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (callback == null) { if (finalizer != null) { - finalizer.run(); + queueHandler.async(finalizer, null); } return null; } else { @@ -859,9 +925,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -869,8 +933,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send() { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); + } } /** @@ -981,9 +1047,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); @@ -1052,38 +1116,25 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int sectionIndex, final PalettedContainerRO> data ) { - PalettedContainer> biomeData; - if (data instanceof PalettedContainer> palettedContainer) { - biomeData = palettedContainer; - } else { - LOGGER.warn( - "Cannot correctly set biomes to world, existing biomes may be lost. Expected class " + - "type {} but got {}", - PalettedContainer.class.getSimpleName(), - data.getClass().getSimpleName() - ); - biomeData = data.recreate(); - } BiomeType[] sectionBiomes; if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { - return biomeData; + return null; } + PalettedContainer> biomeData = data.recreate(); for (int y = 0, index = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { for (int x = 0; x < 4; x++, index++) { BiomeType biomeType = sectionBiomes[index]; if (biomeType == null) { - continue; + biomeData.set(x, y, z, data.get(x, y, z)); + } else { + biomeData.set( + x, + y, + z, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType)) + ); } - biomeData.set( - x, - y, - z, - biomeHolderIdMap.byIdOrThrow(WorldEditPlugin - .getInstance() - .getBukkitImplAdapter() - .getInternalBiomeId(biomeType)) - ); } } } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java index b6557ef0b..18b557b97 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java @@ -1,21 +1,23 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -24,8 +26,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -37,14 +42,14 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; final LevelChunk levelChunk; - private PalettedContainer>[] biomes = null; + private Holder[][] biomes = null; protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.levelChunk = levelChunk; @@ -55,44 +60,37 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId(DedicatedServer + .getServer() + .registryAccess()))) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -105,7 +103,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -142,7 +141,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BiomeType getBiomeType(int x, int y, int z) { - Holder biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2); + Holder biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2]; return PaperweightPlatformAdapter.adapt(biome, serverLevel); } @@ -171,10 +170,25 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { if (biomes == null) { - biomes = new PalettedContainer[getSectionCount()]; + biomes = new Holder[getSectionCount()][]; + } + if (biomes[layer] == null) { + biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - biomes[layer] = palettedContainer.copy(); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } else { LOGGER.error( "Cannot correctly save biomes to history. Expected class type {} but got {}", @@ -187,7 +201,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -199,6 +213,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } @@ -213,6 +231,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightMapChunkUtil.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightMapChunkUtil.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightMapChunkUtil.java index 62f5d4e03..6819e5466 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightMapChunkUtil.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightMapChunkUtil.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil= 0 && layer < sections.length) { - return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -238,19 +247,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } try { synchronized (section) { - Unsafe unsafe = ReflectionUtils.getUnsafe(); PalettedContainer blocks = section.getStates(); - ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject( - blocks, - fieldThreadingDetectorOffset - ); + ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks); synchronized (currentThreadingDetector) { - Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset); + Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector); if (currentLock instanceof DelegateSemaphore delegateSemaphore) { return delegateSemaphore; } DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); - unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock); + fieldLock.set(currentThreadingDetector, newLock); return newLock; } } @@ -286,8 +291,23 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); try { - CraftChunk chunk = (CraftChunk) future.get(); - return chunk.getHandle(); + CraftChunk chunk; + try { + chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + } catch (TimeoutException e) { + String world = serverLevel.getWorld().getName(); + // We've already taken 10 seconds we can afford to wait a little here. + boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + if (loaded) { + LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); + // Retry chunk load + chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + } else { + throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); + } + } + addTicket(serverLevel, chunkX, chunkZ); + return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); } catch (Throwable e) { e.printStackTrace(); } @@ -299,7 +319,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { // Ensure chunk is definitely loaded before applying a ticket io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel .getChunkSource() - .addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + .addRegionTicket(ChunkHolderManager.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { @@ -312,7 +332,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -321,40 +341,42 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { LevelChunk levelChunk; if (PaperLib.isPaper()) { // getChunkAtIfLoadedImmediately is paper only - levelChunk = nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ); + levelChunk = nmsWorld.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = ((Optional) ((Either) chunkHolder - .getTickingChunkFuture() // method is not present with new paper chunk system - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) - .orElse(null); + levelChunk = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); } if (levelChunk == null) { return; } - TaskManager.taskManager().task(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - true - ); + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } + MinecraftServer.getServer().execute(() -> { + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } @@ -384,7 +406,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @Nullable PalettedContainer> biomes ) { if (set == null) { - return newChunkSection(layer, biomeRegistry, biomes); + return newChunkSection(biomeRegistry, biomes); } final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); @@ -457,12 +479,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { .getBukkitImplAdapter() .getInternalBiomeId( BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); } - return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); + return new LevelChunkSection(blockStatePalettedContainer, biomes); } catch (final Throwable e) { throw e; } finally { @@ -475,20 +496,26 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { @SuppressWarnings("deprecation") // Only deprecated in paper private static LevelChunkSection newChunkSection( - int layer, Registry biomeRegistry, @Nullable PalettedContainer> biomes ) { if (biomes == null) { - return new LevelChunkSection(layer, biomeRegistry); + return new LevelChunkSection(biomeRegistry); } PalettedContainer dataPaletteBlocks = new PalettedContainer<>( Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), - PalettedContainer.Strategy.SECTION_STATES, - null + PalettedContainer.Strategy.SECTION_STATES ); - return new LevelChunkSection(layer, dataPaletteBlocks, biomes); + return new LevelChunkSection(dataPaletteBlocks, biomes); + } + + public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer> biomes) { + try { + fieldBiomes.set(section, biomes); + } catch (IllegalAccessException e) { + LOGGER.error("Could not set biomes to chunk section", e); + } } /** @@ -525,8 +552,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { PalettedContainer> biomePalettedContainer = new PalettedContainer<>( biomeRegistry, biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); final Palette> biomePalette; @@ -604,7 +630,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } public static BiomeType adapt(Holder biome, LevelAccessor levelAccessor) { - final Registry biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY); + final Registry biomeRegistry = levelAccessor.registryAccess().registryOrThrow(BIOME); if (biomeRegistry.getKey(biome.value()) == null) { return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN : null; @@ -630,32 +656,22 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static List getEntities(LevelChunk chunk) { - ExceptionCollector collector = new ExceptionCollector<>(); if (PaperLib.isPaper()) { - if (POST_CHUNK_REWRITE) { - try { - //noinspection unchecked - return (List) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ)); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e); - } - } try { - EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk); - return List.of(entityList.getRawData()); - } catch (IllegalAccessException e) { - collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e)); - // fall through + //noinspection unchecked + return (List) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level + .moonrise$getEntityLookup() + .getChunk(chunk.locX, chunk.locZ)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Failed to lookup entities [PAPER=true]", e); } } try { //noinspection unchecked return ((PersistentEntitySectionManager) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos()); } catch (IllegalAccessException e) { - collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e)); + throw new RuntimeException("Failed to lookup entities [PAPER=false]", e); } - collector.throwIfPresent(); - return List.of(); } record FakeIdMapBlock(int size) implements IdMap { diff --git a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java similarity index 99% rename from worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightPostProcessor.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java index a3f016f42..3b4c47087 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R2/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java new file mode 100644 index 000000000..aa7b19b39 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java @@ -0,0 +1,80 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; + +import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.util.Unit; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.status.ChunkPyramid; +import net.minecraft.world.level.chunk.status.ChunkStatus; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.IntConsumer; + +public class PaperweightStarlightRelighter extends StarlightRelighter { + + private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkPyramid.LOADING_PYRAMID + .getStepTo(ChunkStatus.FULL) + .getAccumulatedRadiusOf(ChunkStatus.LIGHT); + + public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + super(serverLevel, queue); + } + + @Override + protected ChunkPos createChunkPos(final long chunkKey) { + return new ChunkPos(chunkKey); + } + + @Override + protected long asLong(final int chunkX, final int chunkZ) { + return ChunkPos.asLong(chunkX, chunkZ); + } + + @Override + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); + } + + protected void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ) { + try { + serverLevel.getChunkSource().getLightEngine().starlight$serverRelightChunks(coords, chunkCallback, processCallback); + } catch (Exception e) { + LOGGER.error("Error occurred on relighting", e); + } + } + + /* + * Allow the server to unload the chunks again. + * Also, if chunk packets are sent delayed, we need to do that here + */ + protected void postProcessChunks(Set coords) { + boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; + for (ChunkPos pos : coords) { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(new IntPair(x, z), serverLevel, x, z); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighterFactory.java similarity index 70% rename from worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighterFactory.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighterFactory.java index d7ff69151..beaffc9a6 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighterFactory.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighterFactory.java @@ -1,23 +1,20 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.bukkit.craftbukkit.CraftWorld; import javax.annotation.Nonnull; public class PaperweightStarlightRelighterFactory implements RelighterFactory { @Override - public @Nonnull - @SuppressWarnings("rawtypes") - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { org.bukkit.World w = Bukkit.getWorld(world.getName()); if (w == null) { return NullRelighter.INSTANCE; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/nbt/PaperweightLazyCompoundTag.java similarity index 91% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java rename to worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/nbt/PaperweightLazyCompoundTag.java index a890d66a4..e2ed21584 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/nbt/PaperweightLazyCompoundTag.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.LazyCompoundTag; @@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.nbt.NumericTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.ArrayList; import java.util.Collections; @@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { @Override @SuppressWarnings("unchecked") - public Map getValue() { + public Map> getValue() { if (compoundTag == null) { compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get()); } @@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @Override - public CompoundBinaryTag asBinaryTag() { + public LinCompoundTag toLinTag() { getValue(); - return compoundTag.asBinaryTag(); + return compoundTag.toLinTag(); } public boolean containsKey(String key) { @@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key) { + public List> getList(String key) { net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); if (tag instanceof net.minecraft.nbt.ListTag nbtList) { - ArrayList list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); for (net.minecraft.nbt.Tag elem : nbtList) { if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) { list.add(new PaperweightLazyCompoundTag(compoundTag)); @@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag { } @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { + public > List getList(String key, Class listType) { ListTag listTag = getListTag(key); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/regen/PaperweightRegen.java new file mode 100644 index 000000000..f62ae8e5d --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/regen/PaperweightRegen.java @@ -0,0 +1,302 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.regen; + +import com.fastasyncworldedit.bukkit.adapter.Regenerator; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.queue.IChunkCache; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.RegenOptions; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.generator.BiomeProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightRegen extends Regenerator { + + private static final Field serverWorldsField; + private static final Field paperConfigField; + private static final Field generatorSettingBaseSupplierField; + + + static { + try { + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + Field tmpPaperConfigField; + try { //only present on paper + tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); + tmpPaperConfigField.setAccessible(true); + } catch (Exception e) { + tmpPaperConfigField = null; + } + paperConfigField = tmpPaperConfigField; + + generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( + "settings", "e")); + generatorSettingBaseSupplierField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //runtime + private ServerLevel originalServerWorld; + private ServerLevel freshWorld; + private LevelStorageSource.LevelStorageAccess session; + + private Path tempDir; + + public PaperweightRegen( + World originalBukkitWorld, + Region region, + Extent target, + RegenOptions options + ) { + super(originalBukkitWorld, region, target, options); + } + + @Override + protected void runTasks(final BooleanSupplier shouldKeepTicking) { + while (shouldKeepTicking.getAsBoolean()) { + if (!this.freshWorld.getChunkSource().pollTask()) { + return; + } + } + } + + @Override + protected boolean prepare() { + this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); + seed = options.getSeed().orElse(originalServerWorld.getSeed()); + return true; + } + + @Override + protected boolean initNewWorld() throws Exception { + //world folder + tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + + //prepare for world init (see upstream implementation for reference) + org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); + org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); + ResourceKey levelStemResourceKey = getWorldDimKey(environment); + session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); + PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; + + MinecraftServer server = originalServerWorld.getCraftServer().getServer(); + WorldOptions originalOpts = originalWorldData.worldGenOptions(); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + LevelSettings newWorldSettings = new LevelSettings( + "faweregentempworld", + originalWorldData.settings.gameType(), + originalWorldData.settings.hardcore(), + originalWorldData.settings.difficulty(), + originalWorldData.settings.allowCommands(), + originalWorldData.settings.gameRules(), + originalWorldData.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + originalWorldData.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : originalWorldData.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + BiomeProvider biomeProvider = getBiomeProvider(); + + + //init world + freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( + server, + server.executor, + session, + newWorldData, + originalServerWorld.dimension(), + new LevelStem( + originalServerWorld.dimensionTypeRegistration(), + originalServerWorld.getChunkSource().getGenerator() + ), + new RegenNoOpWorldLoadListener(), + originalServerWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalServerWorld.getRandomSequences(), + environment, + generator, + biomeProvider + ) { + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; + + @Override + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + if (options.hasBiomeType()) { + return singleBiome; + } + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } + }).get(); + freshWorld.noSave = true; + removeWorldFromWorldsMap(); + newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name + if (paperConfigField != null) { + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); + } + return true; + } + + @Override + protected void cleanup() { + try { + session.close(); + } catch (Exception ignored) { + } + + //shutdown chunk provider + try { + Fawe.instance().getQueueHandler().sync(() -> { + try { + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ignored) { + } + + //remove world from server + try { + Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); + } catch (Exception ignored) { + } + + //delete directory + try { + SafeFiles.tryHardToDeleteDir(tempDir); + } catch (Exception ignored) { + } + } + + @Override + protected IChunkCache initSourceQueueCache() { + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); + } + + //util + @SuppressWarnings("unchecked") + private void removeWorldFromWorldsMap() { + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { + return switch (env) { + case NETHER -> LevelStem.NETHER; + case THE_END -> LevelStem.END; + default -> LevelStem.OVERWORLD; + }; + } + + private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { + + private RegenNoOpWorldLoadListener() { + } + + @Override + public void updateSpawnPos(@NotNull ChunkPos spawnPos) { + } + + @Override + public void onStatusChange( + final @NotNull ChunkPos pos, + @org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status + ) { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + } + + // TODO Paper only(?) @Override + public void setChunkRadius(int radius) { + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts similarity index 64% rename from worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts rename to worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts index a0ca70d2b..fb3f7fcd2 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts @@ -11,6 +11,7 @@ repositories { } dependencies { - the().paperDevBundle("1.19.2-R0.1-20221206.184705-189") + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.3-R0.1-SNAPSHOT/ + the().paperDevBundle("1.21.3-R0.1-20241124.214153-64") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightAdapter.java similarity index 54% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java rename to worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightAdapter.java index 47389b357..6d61641d7 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightAdapter.java @@ -17,23 +17,23 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; -import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3.PaperweightFaweAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.Extent; @@ -43,10 +43,6 @@ import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; @@ -54,22 +50,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeCategory; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; @@ -77,26 +60,34 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.item.ItemType; +import net.minecraft.SharedConstants; import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.StringRepresentable; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Clearable; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -109,33 +100,49 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.StructureBlockEntity; import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_18_R2.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.generator.ChunkGenerator; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinEndTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -143,9 +150,9 @@ import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.OptionalInt; @@ -154,61 +161,51 @@ import java.util.Set; import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public final class PaperweightAdapter implements BukkitImplAdapter { - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE - ); + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + private final Field serverWorldsField; private final Method getChunkFutureMethod; private final Field chunkProviderExecutorField; - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); + private final PaperweightDataConverters dataFixer; + private final Watchdog watchdog; // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ - private final Watchdog watchdog; - private final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { // A simple test CraftServer.class.cast(Bukkit.getServer()); - int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2975) { - throw new UnsupportedClassVersionError("Not 1.18.2!"); + int dataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion(); + if (dataVersion != 4082) { + throw new UnsupportedClassVersionError("Not 1.21.3!"); } serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod( - Refraction.pickName("getChunkFutureMainThread", "c"), - int.class, int.class, ChunkStatus.class, boolean.class + StaticRefraction.GET_CHUNK_FUTURE_MAIN_THREAD, + int.class, int.class, ChunkStatus.class, boolean.class ); getChunkFutureMethod.setAccessible(true); chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField( - Refraction.pickName("mainThreadProcessor", "g") + StaticRefraction.MAIN_THREAD_PROCESSOR ); chunkProviderExecutorField.setAccessible(true); - new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); + this.dataFixer = new PaperweightDataConverters(dataVersion, this); Watchdog watchdog; try { @@ -225,19 +222,24 @@ public final class PaperweightAdapter implements BukkitImplAdapter t.create(world)).orElse(null); + return EntityType.byString(id).map(t -> t.create(world, EntitySpawnReason.COMMAND)).orElse(null); } /** * Write the given NBT data into the given entity. * * @param entity the entity - * @param tag the tag + * @param tag the tag */ private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { entity.load(tag); @@ -277,18 +279,140 @@ public final class PaperweightAdapter implements BukkitImplAdapter, Object> states = state.getStates(); + newState = applyProperties(mcBlock.getStateDefinition(), newState, states); + final int combinedId = Block.getId(newState); + return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); + } + + public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + int internalId = Block.getId(blockState); + BlockState state = BlockStateIdAccess.getBlockStateById(internalId); + if (state == null) { + state = BukkitAdapter.adapt(CraftBlockData.createData(blockState)); + } + + return state; + } + + public BiomeType adapt(Biome biome) { + var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess() + .lookupOrThrow(Registries.BIOME).getKey(biome); + if (mcBiome == null) { + return null; + } + return BiomeType.REGISTRY.get(mcBiome.toString()); + } + + public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) { + int internalId = BlockStateIdAccess.getBlockStateId(blockState); + return Block.stateById(internalId); + } + + @Override + public BlockState getBlock(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); + return adapt(blockData); + } + + @Override + public BaseBlock getFullBlock(Location location) { + BlockState state = getBlock(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + + // Read the NBT data + BlockEntity te = chunk.getBlockEntity(blockPos); + if (te != null) { + net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess()); + return state.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))); + } + + return state.toBaseBlock(); + } + + private static final HashMap> biomeTypeToNMSCache = new HashMap<>(); + private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); + + @Override + public BiomeType getBiome(Location location) { + checkNotNull(location); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + + return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), + b -> BiomeType.REGISTRY.get(b.unwrapKey().orElseThrow().location().toString())); + } + + @Override + public void setBiome(Location location, BiomeType biome) { + checkNotNull(location); + checkNotNull(biome); + + CraftWorld craftWorld = ((CraftWorld) location.getWorld()); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = craftWorld.getHandle(); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, + b -> handle.registryAccess().lookupOrThrow(Registries.BIOME) + .getOrThrow(ResourceKey.create(Registries.BIOME, ResourceLocation.parse(b.id()))))); + chunk.markUnsaved(); + } + + @Override + public WorldNativeAccess createWorldNativeAccess(World world) { + return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } private static net.minecraft.core.Direction adapt(Direction face) { @@ -309,111 +433,33 @@ public final class PaperweightAdapter implements BukkitImplAdapter, Object> states = state.getStates(); - newState = applyProperties(mcBlock.getStateDefinition(), newState, states); - final int combinedId = Block.getId(newState); - return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); - } - - @Override - public BlockState getBlock(Location location) { - checkNotNull(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); - int internalId = Block.getId(blockData); - BlockState state = BlockStateIdAccess.getBlockStateById(internalId); - if (state == null) { - org.bukkit.block.Block bukkitBlock = location.getBlock(); - state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); - } - - return state; - } - - @Override - public BaseBlock getFullBlock(Location location) { - BlockState state = getBlock(location); - - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - final ServerLevel handle = craftWorld.getHandle(); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); - final BlockPos blockPos = new BlockPos(x, y, z); - - // Read the NBT data - BlockEntity te = chunk.getBlockEntity(blockPos); - if (te != null) { - net.minecraft.nbt.CompoundTag tag = te.saveWithId(); - //FAWE start - BinaryTag - return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - //FAWE end - } - - return state.toBaseBlock(); - } - - @Override - public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); - } - @SuppressWarnings({"rawtypes", "unchecked"}) private net.minecraft.world.level.block.state.BlockState applyProperties( - StateDefinition stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states + StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, + Map, Object> states ) { for (Map.Entry, Object> state : states.entrySet()) { net.minecraft.world.level.block.state.properties.Property property = - stateContainer.getProperty(state.getKey().getName()); + stateContainer.getProperty(state.getKey().getName()); Comparable value = (Comparable) state.getValue(); // we may need to adapt this value, depending on the source prop - if (property instanceof DirectionProperty) { - Direction dir = (Direction) value; - value = adapt(dir); - } else if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - String enumName = (String) value; - value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property) - .getValue(enumName).orElseThrow(() -> - new IllegalStateException( - "Enum property " + property.getName() + " does not contain " + enumName - ) - ); + if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty enumProperty) { + if (enumProperty.getValueClass() == net.minecraft.core.Direction.class) { + value = adapt((Direction) value); + } else { + String enumName = (String) value; + value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property) + .getValue(enumName).orElseThrow(() -> + new IllegalStateException( + "Enum property " + property.getName() + " does not contain " + enumName + ) + ); + } } - newState = newState.setValue( - (net.minecraft.world.level.block.state.properties.Property) property, - (Comparable) value + (net.minecraft.world.level.block.state.properties.Property) property, + (Comparable) value ); } return newState; @@ -426,16 +472,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter (CompoundBinaryTag) toNativeBinary(tag)) + EntityTypes.get(id), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)) ); - //FAWE end } @Nullable @@ -447,27 +496,48 @@ public final class PaperweightAdapter implements BukkitImplAdapter { + loadedEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + return loadedEntity; + }); if (createdEntity != null) { - CompoundBinaryTag nativeTag = state.getNbt(); - if (nativeTag != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - readTagIntoEntity(tag, createdEntity); - } - - createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - - worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM); + worldServer.addFreshEntityWithPassengers(createdEntity, SpawnReason.CUSTOM); return createdEntity.getBukkitEntity(); } else { return null; } } + // This removes all unwanted tags from the main entity and all its passengers + private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) { + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + + // Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive + if (tag.contains("Passengers", LinTagId.LIST.id())) { + net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", LinTagId.COMPOUND.id()); + + for (int i = 0; i < nbttaglist.size(); ++i) { + removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i)); + } + } + } + @Override public Component getRichBlockName(BlockType blockType) { return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); @@ -480,28 +550,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); + private static final LoadingCache, Property> PROPERTY_CACHE = + CacheBuilder.newBuilder().build(CacheLoader.from(PaperweightFaweAdapter::adaptProperty)); @SuppressWarnings({ "rawtypes" }) @Override @@ -509,7 +562,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter> properties = new TreeMap<>(); Block block = getBlockFromType(blockType); StateDefinition blockStateList = - block.getStateDefinition(); + block.getStateDefinition(); for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { Property property = PROPERTY_CACHE.getUnchecked(state); properties.put(property.getName(), property); @@ -517,50 +570,76 @@ public final class PaperweightAdapter implements BukkitImplAdapter CompoundTag @Override - public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) { - ((CraftPlayer) player).getHandle().networkManager.send(ClientboundBlockEntityDataPacket.create( - new StructureBlockEntity( - new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - Blocks.STRUCTURE_BLOCK.defaultBlockState() - ), - __ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) + public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) { + var structureBlock = new StructureBlockEntity( + new BlockPos(pos.x(), pos.y(), pos.z()), + Blocks.STRUCTURE_BLOCK.defaultBlockState() + ); + structureBlock.setLevel(((CraftPlayer) player).getHandle().level()); + ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create( + structureBlock, + (blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData) )); } - //FAWE end @Override public void sendFakeOP(Player player) { - ((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket( - ((CraftPlayer) player).getHandle(), (byte) 28 + ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( + ((CraftPlayer) player).getHandle(), (byte) 28 )); } + /** + * For serializing and deserializing components. + */ + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + @Override - public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { - ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); + public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + var registryAccess = DedicatedServer.getServer().registryAccess(); + ItemStack stack = new ItemStack( + registryAccess.lookupOrThrow(Registries.ITEM).getOrThrow( + ResourceKey.create(Registries.ITEM, ResourceLocation.parse(baseItemStack.getType().id())) + ), + baseItemStack.getAmount() + ); + LinCompoundTag nbt = baseItemStack.getNbt(); + if (nbt != null) { + DataComponentPatch componentPatch = COMPONENTS_CODEC.parse( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + fromNativeLin(nbt) + ).getOrThrow(); + stack.applyComponents(componentPatch); + } return CraftItemStack.asCraftMirror(stack); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + var registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - //FAWE start - CBT > CT - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - //FAWE end - return weStack; + CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), itemStack.getAmount()); } + private final LoadingCache fakePlayers + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); + @Override - public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { + public boolean simulateItemUse(World world, BlockVector3 position, BaseItem item, Direction face) { CraftWorld craftWorld = (CraftWorld) world; ServerLevel worldServer = craftWorld.getHandle(); - ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack - ? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); - stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); + ItemStack stack = CraftItemStack.asNMSCopy(adapt( + item instanceof BaseItemStack + ? ((BaseItemStack) item) + : new BaseItemStack(item.getType(), item.getNbtReference(), 1) + )); PaperweightFakePlayer fakePlayer; try { @@ -569,24 +648,20 @@ public final class PaperweightAdapter implements BukkitImplAdapter worldDimKey = getWorldDimKey(env); - try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { + try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("worldeditregentempworld", worldDimKey)) { ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() - .getWorldData().overworldData(); - WorldGenSettings originalOpts = levelProperties.worldGenSettings(); + .getWorldData().overworldData(); + WorldOptions originalOpts = levelProperties.worldGenOptions(); long seed = options.getSeed().orElse(originalWorld.getSeed()); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) - : originalOpts; + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; LevelSettings newWorldSettings = new LevelSettings( - "faweregentempworld", - levelProperties.settings.gameType(), - levelProperties.settings.hardcore(), - levelProperties.settings.difficulty(), - levelProperties.settings.allowCommands(), - levelProperties.settings.gameRules(), - levelProperties.settings.getDataPackConfig() + "worldeditregentempworld", + levelProperties.settings.gameType(), + levelProperties.settings.hardcore(), + levelProperties.settings.difficulty(), + levelProperties.settings.allowCommands(), + levelProperties.settings.gameRules(), + levelProperties.settings.getDataConfiguration() ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); + + @SuppressWarnings("deprecation") + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + levelProperties.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : levelProperties.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); ServerLevel freshWorld = new ServerLevel( - originalWorld.getServer(), - originalWorld.getServer().executor, - session, newWorldData, - originalWorld.dimension(), + originalWorld.getServer(), + originalWorld.getServer().executor, + session, newWorldData, + originalWorld.dimension(), + new LevelStem( originalWorld.dimensionTypeRegistration(), - new NoOpWorldLoadListener(), - newOpts.dimensions().get(worldDimKey).generator(), - originalWorld.isDebug(), - seed, - ImmutableList.of(), - false, - env, gen, - bukkitWorld.getBiomeProvider() + originalWorld.getChunkSource().getGenerator() + ), + new NoOpWorldLoadListener(), + originalWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalWorld.getRandomSequences(), + env, + gen, + bukkitWorld.getBiomeProvider() ); try { regenForWorld(region, extent, freshWorld, options); @@ -666,8 +751,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("worldeditregentempworld"); } catch (IllegalAccessException ignored) { } SafeFiles.tryHardToDeleteDir(tempDir); @@ -675,7 +760,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter> chunkLoadings = submitChunkLoadTasks(region, serverWorld); BlockableEventLoop executor; try { @@ -695,7 +779,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null + ftr.isDone() && Futures.getUnchecked(ftr) == null )) { return false; } @@ -710,7 +794,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter (LinCompoundTag) toNativeLin(tag))); } extent.setBlock(vec, state.toBaseBlock()); if (options.shouldRegenBiomes()) { - Biome origBiome = chunk.getNoiseBiome(vec.getX(), vec.getY(), vec.getZ()).value(); + Biome origBiome = chunk.getNoiseBiome(vec.x(), vec.y(), vec.z()).value(); BiomeType adaptedBiome = adapt(serverWorld, origBiome); if (adaptedBiome != null) { extent.setBiome(vec, adaptedBiome); @@ -743,9 +825,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter>) - getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) + ((CompletableFuture>) + getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true)) + .thenApply(either -> either.orElse(null)) ); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Couldn't load chunk for regen.", e); @@ -766,16 +848,25 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.NEIGHBORS, + SideEffect.LIGHTING, + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.EVENTS, + SideEffect.UPDATE + ); + @Override public Set getSupportedSideEffects() { return SUPPORTED_SIDE_EFFECTS; } @Override - public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) { + public boolean clearContainerBlockContents(World world, BlockVector3 pt) { ServerLevel originalWorld = ((CraftWorld) world).getHandle(); - BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ())); + BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z())); if (entity instanceof Clearable) { ((Clearable) entity).clearContent(); return true; @@ -783,6 +874,45 @@ public final class PaperweightAdapter implements BukkitImplAdapter biomeRegistry = server.registryAccess().lookupOrThrow(Registries.BIOME); + biomeRegistry.getTags().forEach(tag -> { + String key = tag.key().location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.get(tag.key()) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(this::adapt) + .collect(Collectors.toSet())) + ); + } + }); + } + + @Override + public void sendBiomeUpdates(World world, Iterable chunks) { + ServerLevel originalWorld = ((CraftWorld) world).getHandle(); + + List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); + for (BlockVector2 chunk : chunks) { + nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); + } + originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + } + // ------------------------------------------------------------------------ // Code that is less likely to break // ------------------------------------------------------------------------ @@ -794,53 +924,50 @@ public final class PaperweightAdapter implements BukkitImplAdapter toNativeLin(net.minecraft.nbt.Tag foreign) { if (foreign == null) { return null; } if (foreign instanceof net.minecraft.nbt.CompoundTag) { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); Set foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys(); for (String str : foreignKeys) { net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str); - values.put(str, toNativeBinary(base)); + values.put(str, toNativeLin(base)); } - return CompoundBinaryTag.from(values); + return LinCompoundTag.of(values); } else if (foreign instanceof net.minecraft.nbt.ByteTag) { - return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { - return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { - return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); } else if (foreign instanceof net.minecraft.nbt.FloatTag) { - return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); } else if (foreign instanceof net.minecraft.nbt.IntTag) { - return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt()); } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { - return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { - return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); + return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray()); } else if (foreign instanceof net.minecraft.nbt.ListTag) { try { - return toNativeList((net.minecraft.nbt.ListTag) foreign); + return toNativeLinList((net.minecraft.nbt.ListTag) foreign); } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); - return ListBinaryTag.empty(); + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); } } else if (foreign instanceof net.minecraft.nbt.LongTag) { - return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong()); } else if (foreign instanceof net.minecraft.nbt.ShortTag) { - return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); } else if (foreign instanceof net.minecraft.nbt.StringTag) { - return StringBinaryTag.of(foreign.getAsString()); + return LinStringTag.of(foreign.getAsString()); } else if (foreign instanceof net.minecraft.nbt.EndTag) { - return EndBinaryTag.get(); - } else { - throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + return LinEndTag.instance(); } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); } /** @@ -848,17 +975,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter values = ListBinaryTag.builder(); + private LinListTag toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + LinListTag.Builder> builder = LinListTag.builder( + LinTagType.fromId(LinTagId.fromId(foreign.getElementType())) + ); for (net.minecraft.nbt.Tag tag : foreign) { - values.add(toNativeBinary(tag)); + builder.add(toNativeLin(tag)); } - return values.build(); + return builder.build(); } /** @@ -868,49 +997,48 @@ public final class PaperweightAdapter implements BukkitImplAdapter foreign) { if (foreign == null) { return null; } - if (foreign instanceof CompoundBinaryTag) { + if (foreign instanceof LinCompoundTag compoundTag) { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - for (String key : ((CompoundBinaryTag) foreign).keySet()) { - tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key))); + for (var entry : compoundTag.value().entrySet()) { + tag.put(entry.getKey(), fromNativeLin(entry.getValue())); } return tag; - } else if (foreign instanceof ByteBinaryTag) { - return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value()); - } else if (foreign instanceof ByteArrayBinaryTag) { - return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value()); - } else if (foreign instanceof DoubleBinaryTag) { - return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value()); - } else if (foreign instanceof FloatBinaryTag) { - return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value()); - } else if (foreign instanceof IntBinaryTag) { - return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value()); - } else if (foreign instanceof IntArrayBinaryTag) { - return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); - } else if (foreign instanceof LongArrayBinaryTag) { - return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag foreignList) { + } else if (foreign instanceof LinByteTag byteTag) { + return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte()); + } else if (foreign instanceof LinByteArrayTag byteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value()); + } else if (foreign instanceof LinDoubleTag doubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble()); + } else if (foreign instanceof LinFloatTag floatTag) { + return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat()); + } else if (foreign instanceof LinIntTag intTag) { + return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt()); + } else if (foreign instanceof LinIntArrayTag intArrayTag) { + return new net.minecraft.nbt.IntArrayTag(intArrayTag.value()); + } else if (foreign instanceof LinLongArrayTag longArrayTag) { + return new net.minecraft.nbt.LongArrayTag(longArrayTag.value()); + } else if (foreign instanceof LinListTag listTag) { net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); - for (BinaryTag t : foreignList) { - tag.add(fromNativeBinary(t)); + for (var t : listTag.value()) { + tag.add(fromNativeLin(t)); } return tag; - } else if (foreign instanceof LongBinaryTag) { - return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value()); - } else if (foreign instanceof ShortBinaryTag) { - return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value()); - } else if (foreign instanceof StringBinaryTag) { - return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value()); - } else if (foreign instanceof EndBinaryTag) { + } else if (foreign instanceof LinLongTag longTag) { + return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong()); + } else if (foreign instanceof LinShortTag shortTag) { + return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort()); + } else if (foreign instanceof LinStringTag stringTag) { + return net.minecraft.nbt.StringTag.valueOf(stringTag.value()); + } else if (foreign instanceof LinEndTag) { return net.minecraft.nbt.EndTag.INSTANCE; } else { throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); } } - //FAWE end @Override public boolean supportsWatchdog() { @@ -922,56 +1050,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.mojang.datafixers.DSL.TypeReference; +import com.mojang.datafixers.DataFixer; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.serialization.Dynamic; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.FloatTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.StringUtil; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.datafix.fixes.References; +import net.minecraft.world.item.DyeColor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; + +import javax.annotation.Nullable; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) + * + *

+ * We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy + * which is safer, faster and cleaner code. + *

+ * + *

+ * The pre DFU code did not fail when the Source version was unknown. + *

+ * + *

+ * This class also provides util methods for converting compounds to wrap the update call to + * receive the source version in the compound + *

+ */ +@SuppressWarnings({ "rawtypes", "unchecked" }) +class PaperweightDataConverters implements com.sk89q.worldedit.world.DataFixer { + + @SuppressWarnings("unchecked") + @Override + public T fixUp(FixType type, T original, int srcVer) { + if (type == FixTypes.CHUNK) { + return (T) fixChunk((LinCompoundTag) original, srcVer); + } else if (type == FixTypes.BLOCK_ENTITY) { + return (T) fixBlockEntity((LinCompoundTag) original, srcVer); + } else if (type == FixTypes.ENTITY) { + return (T) fixEntity((LinCompoundTag) original, srcVer); + } else if (type == FixTypes.BLOCK_STATE) { + return (T) fixBlockState((String) original, srcVer); + } else if (type == FixTypes.ITEM_TYPE) { + return (T) fixItemType((String) original, srcVer); + } else if (type == FixTypes.BIOME) { + return (T) fixBiome((String) original, srcVer); + } + return original; + } + + private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(originalChunk); + CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); + } + + private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(origTileEnt); + CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); + } + + private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { + CompoundTag tag = (CompoundTag) adapter.fromNativeLin(origEnt); + CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); + return (LinCompoundTag) adapter.toNativeLin(fixed); + } + + private String fixBlockState(String blockState, int srcVer) { + CompoundTag stateNBT = stateToNBT(blockState); + Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); + CompoundTag fixed = (CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); + return nbtToState(fixed); + } + + private String nbtToState(CompoundTag tagCompound) { + StringBuilder sb = new StringBuilder(); + sb.append(tagCompound.getString("Name")); + if (tagCompound.contains("Properties", 10)) { + sb.append('['); + CompoundTag props = tagCompound.getCompound("Properties"); + sb.append(props.getAllKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(","))); + sb.append(']'); + } + return sb.toString(); + } + + private static CompoundTag stateToNBT(String blockState) { + int propIdx = blockState.indexOf('['); + CompoundTag tag = new CompoundTag(); + if (propIdx < 0) { + tag.putString("Name", blockState); + } else { + tag.putString("Name", blockState.substring(0, propIdx)); + CompoundTag propTag = new CompoundTag(); + String props = blockState.substring(propIdx + 1, blockState.length() - 1); + String[] propArr = props.split(","); + for (String pair : propArr) { + final String[] split = pair.split("="); + propTag.putString(split[0], split[1]); + } + tag.put("Properties", propTag); + } + return tag; + } + + private String fixBiome(String key, int srcVer) { + return fixName(key, srcVer, References.BIOME); + } + + private String fixItemType(String key, int srcVer) { + return fixName(key, srcVer, References.ITEM_NAME); + } + + private static String fixName(String key, int srcVer, TypeReference type) { + return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, DATA_VERSION) + .getValue().getAsString(); + } + + private final PaperweightAdapter adapter; + + private static final NbtOps OPS_NBT = NbtOps.INSTANCE; + private static final int LEGACY_VERSION = 1343; + private static int DATA_VERSION; + static PaperweightDataConverters INSTANCE; + + private final Map> converters = new EnumMap<>(LegacyType.class); + private final Map> inspectors = new EnumMap<>(LegacyType.class); + + // Set on build + private DataFixer fixer; + private static final Map DFU_TO_LEGACY = new HashMap<>(); + + public enum LegacyType { + LEVEL(References.LEVEL), + PLAYER(References.PLAYER), + CHUNK(References.CHUNK), + BLOCK_ENTITY(References.BLOCK_ENTITY), + ENTITY(References.ENTITY), + ITEM_INSTANCE(References.ITEM_STACK), + OPTIONS(References.OPTIONS), + STRUCTURE(References.STRUCTURE); + + private final TypeReference type; + + LegacyType(TypeReference type) { + this.type = type; + DFU_TO_LEGACY.put(type.typeName(), this); + } + + public TypeReference getDFUType() { + return type; + } + } + + PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { + DATA_VERSION = dataVersion; + INSTANCE = this; + this.adapter = adapter; + registerConverters(); + registerInspectors(); + this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); + } + + @SuppressWarnings("unchecked") + private class WrappedDataFixer implements DataFixer { + private final DataFixer realFixer; + + WrappedDataFixer(DataFixer realFixer) { + this.realFixer = realFixer; + } + + @Override + public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { + LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); + if (sourceVer < LEGACY_VERSION && legacyType != null) { + CompoundTag cmp = (CompoundTag) dynamic.getValue(); + int desiredVersion = Math.min(targetVer, LEGACY_VERSION); + + cmp = convert(legacyType, cmp, sourceVer, desiredVersion); + sourceVer = desiredVersion; + dynamic = new Dynamic(OPS_NBT, cmp); + } + return realFixer.update(type, dynamic, sourceVer, targetVer); + } + + private CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer, int desiredVersion) { + List converters = PaperweightDataConverters.this.converters.get(type); + if (converters != null && !converters.isEmpty()) { + for (DataConverter converter : converters) { + int dataVersion = converter.getDataVersion(); + if (dataVersion > sourceVer && dataVersion <= desiredVersion) { + cmp = converter.convert(cmp); + } + } + } + + List inspectors = PaperweightDataConverters.this.inspectors.get(type); + if (inspectors != null && !inspectors.isEmpty()) { + for (DataInspector inspector : inspectors) { + cmp = inspector.inspect(cmp, sourceVer, desiredVersion); + } + } + + return cmp; + } + + @Override + public Schema getSchema(int i) { + return realFixer.getSchema(i); + } + } + + public static CompoundTag convert(LegacyType type, CompoundTag cmp) { + return convert(type.getDFUType(), cmp); + } + + public static CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer) { + return convert(type.getDFUType(), cmp, sourceVer); + } + + public static CompoundTag convert(LegacyType type, CompoundTag cmp, int sourceVer, int targetVer) { + return convert(type.getDFUType(), cmp, sourceVer, targetVer); + } + + public static CompoundTag convert(TypeReference type, CompoundTag cmp) { + int i = cmp.contains("DataVersion", 99) ? cmp.getInt("DataVersion") : -1; + return convert(type, cmp, i); + } + + public static CompoundTag convert(TypeReference type, CompoundTag cmp, int sourceVer) { + return convert(type, cmp, sourceVer, DATA_VERSION); + } + + public static CompoundTag convert(TypeReference type, CompoundTag cmp, int sourceVer, int targetVer) { + if (sourceVer >= targetVer) { + return cmp; + } + return (CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); + } + + + public interface DataInspector { + CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer); + } + + public interface DataConverter { + + int getDataVersion(); + + CompoundTag convert(CompoundTag cmp); + } + + + private void registerInspector(LegacyType type, DataInspector inspector) { + this.inspectors.computeIfAbsent(type, k -> new ArrayList<>()).add(inspector); + } + + private void registerConverter(LegacyType type, DataConverter converter) { + int version = converter.getDataVersion(); + + List list = this.converters.computeIfAbsent(type, k -> new ArrayList<>()); + if (!list.isEmpty() && list.get(list.size() - 1).getDataVersion() > version) { + for (int j = 0; j < list.size(); ++j) { + if (list.get(j).getDataVersion() > version) { + list.add(j, converter); + break; + } + } + } else { + list.add(converter); + } + } + + private void registerInspectors() { + registerEntityItemList("EntityHorseDonkey", "SaddleItem", "Items"); + registerEntityItemList("EntityHorseMule", "Items"); + registerEntityItemList("EntityMinecartChest", "Items"); + registerEntityItemList("EntityMinecartHopper", "Items"); + registerEntityItemList("EntityVillager", "Inventory"); + registerEntityItemListEquipment("EntityArmorStand"); + registerEntityItemListEquipment("EntityBat"); + registerEntityItemListEquipment("EntityBlaze"); + registerEntityItemListEquipment("EntityCaveSpider"); + registerEntityItemListEquipment("EntityChicken"); + registerEntityItemListEquipment("EntityCow"); + registerEntityItemListEquipment("EntityCreeper"); + registerEntityItemListEquipment("EntityEnderDragon"); + registerEntityItemListEquipment("EntityEnderman"); + registerEntityItemListEquipment("EntityEndermite"); + registerEntityItemListEquipment("EntityEvoker"); + registerEntityItemListEquipment("EntityGhast"); + registerEntityItemListEquipment("EntityGiantZombie"); + registerEntityItemListEquipment("EntityGuardian"); + registerEntityItemListEquipment("EntityGuardianElder"); + registerEntityItemListEquipment("EntityHorse"); + registerEntityItemListEquipment("EntityHorseDonkey"); + registerEntityItemListEquipment("EntityHorseMule"); + registerEntityItemListEquipment("EntityHorseSkeleton"); + registerEntityItemListEquipment("EntityHorseZombie"); + registerEntityItemListEquipment("EntityIronGolem"); + registerEntityItemListEquipment("EntityMagmaCube"); + registerEntityItemListEquipment("EntityMushroomCow"); + registerEntityItemListEquipment("EntityOcelot"); + registerEntityItemListEquipment("EntityPig"); + registerEntityItemListEquipment("EntityPigZombie"); + registerEntityItemListEquipment("EntityRabbit"); + registerEntityItemListEquipment("EntitySheep"); + registerEntityItemListEquipment("EntityShulker"); + registerEntityItemListEquipment("EntitySilverfish"); + registerEntityItemListEquipment("EntitySkeleton"); + registerEntityItemListEquipment("EntitySkeletonStray"); + registerEntityItemListEquipment("EntitySkeletonWither"); + registerEntityItemListEquipment("EntitySlime"); + registerEntityItemListEquipment("EntitySnowman"); + registerEntityItemListEquipment("EntitySpider"); + registerEntityItemListEquipment("EntitySquid"); + registerEntityItemListEquipment("EntityVex"); + registerEntityItemListEquipment("EntityVillager"); + registerEntityItemListEquipment("EntityVindicator"); + registerEntityItemListEquipment("EntityWitch"); + registerEntityItemListEquipment("EntityWither"); + registerEntityItemListEquipment("EntityWolf"); + registerEntityItemListEquipment("EntityZombie"); + registerEntityItemListEquipment("EntityZombieHusk"); + registerEntityItemListEquipment("EntityZombieVillager"); + registerEntityItemSingle("EntityFireworks", "FireworksItem"); + registerEntityItemSingle("EntityHorse", "ArmorItem"); + registerEntityItemSingle("EntityHorse", "SaddleItem"); + registerEntityItemSingle("EntityHorseMule", "SaddleItem"); + registerEntityItemSingle("EntityHorseSkeleton", "SaddleItem"); + registerEntityItemSingle("EntityHorseZombie", "SaddleItem"); + registerEntityItemSingle("EntityItem", "Item"); + registerEntityItemSingle("EntityItemFrame", "Item"); + registerEntityItemSingle("EntityPotion", "Potion"); + + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItem("TileEntityRecordPlayer", "RecordItem")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityBrewingStand", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityChest", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDispenser", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDropper", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityFurnace", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityHopper", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityShulkerBox", "Items")); + registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorMobSpawnerMobs()); + registerInspector(LegacyType.CHUNK, new DataInspectorChunks()); + registerInspector(LegacyType.ENTITY, new DataInspectorCommandBlock()); + registerInspector(LegacyType.ENTITY, new DataInspectorEntityPassengers()); + registerInspector(LegacyType.ENTITY, new DataInspectorMobSpawnerMinecart()); + registerInspector(LegacyType.ENTITY, new DataInspectorVillagers()); + registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorBlockEntity()); + registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorEntity()); + registerInspector(LegacyType.LEVEL, new DataInspectorLevelPlayer()); + registerInspector(LegacyType.PLAYER, new DataInspectorPlayer()); + registerInspector(LegacyType.PLAYER, new DataInspectorPlayerVehicle()); + registerInspector(LegacyType.STRUCTURE, new DataInspectorStructure()); + } + + private void registerConverters() { + registerConverter(LegacyType.ENTITY, new DataConverterEquipment()); + registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterSignText()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterMaterialId()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionId()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterSpawnEgg()); + registerConverter(LegacyType.ENTITY, new DataConverterMinecart()); + registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterMobSpawner()); + registerConverter(LegacyType.ENTITY, new DataConverterUUID()); + registerConverter(LegacyType.ENTITY, new DataConverterHealth()); + registerConverter(LegacyType.ENTITY, new DataConverterSaddle()); + registerConverter(LegacyType.ENTITY, new DataConverterHanging()); + registerConverter(LegacyType.ENTITY, new DataConverterDropChances()); + registerConverter(LegacyType.ENTITY, new DataConverterRiding()); + registerConverter(LegacyType.ENTITY, new DataConverterArmorStand()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBook()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterCookedFish()); + registerConverter(LegacyType.ENTITY, new DataConverterZombie()); + registerConverter(LegacyType.OPTIONS, new DataConverterVBO()); + registerConverter(LegacyType.ENTITY, new DataConverterGuardian()); + registerConverter(LegacyType.ENTITY, new DataConverterSkeleton()); + registerConverter(LegacyType.ENTITY, new DataConverterZombieType()); + registerConverter(LegacyType.ENTITY, new DataConverterHorse()); + registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterTileEntity()); + registerConverter(LegacyType.ENTITY, new DataConverterEntity()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBanner()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionWater()); + registerConverter(LegacyType.ENTITY, new DataConverterShulker()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterShulkerBoxItem()); + registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterShulkerBoxBlock()); + registerConverter(LegacyType.OPTIONS, new DataConverterLang()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterTotem()); + registerConverter(LegacyType.CHUNK, new DataConverterBedBlock()); + registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBedItem()); + } + + private void registerEntityItemList(String type, String... keys) { + registerInspector(LegacyType.ENTITY, new DataInspectorItemList(type, keys)); + } + + private void registerEntityItemSingle(String type, String key) { + registerInspector(LegacyType.ENTITY, new DataInspectorItem(type, key)); + } + + private void registerEntityItemListEquipment(String type) { + registerEntityItemList(type, "ArmorItems", "HandItems"); + } + + private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); + + static { + final Map map = OLD_ID_TO_KEY_MAP; + map.put("EntityItem", ResourceLocation.parse("item")); + map.put("EntityExperienceOrb", ResourceLocation.parse("xp_orb")); + map.put("EntityAreaEffectCloud", ResourceLocation.parse("area_effect_cloud")); + map.put("EntityGuardianElder", ResourceLocation.parse("elder_guardian")); + map.put("EntitySkeletonWither", ResourceLocation.parse("wither_skeleton")); + map.put("EntitySkeletonStray", ResourceLocation.parse("stray")); + map.put("EntityEgg", ResourceLocation.parse("egg")); + map.put("EntityLeash", ResourceLocation.parse("leash_knot")); + map.put("EntityPainting", ResourceLocation.parse("painting")); + map.put("EntityTippedArrow", ResourceLocation.parse("arrow")); + map.put("EntitySnowball", ResourceLocation.parse("snowball")); + map.put("EntityLargeFireball", ResourceLocation.parse("fireball")); + map.put("EntitySmallFireball", ResourceLocation.parse("small_fireball")); + map.put("EntityEnderPearl", ResourceLocation.parse("ender_pearl")); + map.put("EntityEnderSignal", ResourceLocation.parse("eye_of_ender_signal")); + map.put("EntityPotion", ResourceLocation.parse("potion")); + map.put("EntityThrownExpBottle", ResourceLocation.parse("xp_bottle")); + map.put("EntityItemFrame", ResourceLocation.parse("item_frame")); + map.put("EntityWitherSkull", ResourceLocation.parse("wither_skull")); + map.put("EntityTNTPrimed", ResourceLocation.parse("tnt")); + map.put("EntityFallingBlock", ResourceLocation.parse("falling_block")); + map.put("EntityFireworks", ResourceLocation.parse("fireworks_rocket")); + map.put("EntityZombieHusk", ResourceLocation.parse("husk")); + map.put("EntitySpectralArrow", ResourceLocation.parse("spectral_arrow")); + map.put("EntityShulkerBullet", ResourceLocation.parse("shulker_bullet")); + map.put("EntityDragonFireball", ResourceLocation.parse("dragon_fireball")); + map.put("EntityZombieVillager", ResourceLocation.parse("zombie_villager")); + map.put("EntityHorseSkeleton", ResourceLocation.parse("skeleton_horse")); + map.put("EntityHorseZombie", ResourceLocation.parse("zombie_horse")); + map.put("EntityArmorStand", ResourceLocation.parse("armor_stand")); + map.put("EntityHorseDonkey", ResourceLocation.parse("donkey")); + map.put("EntityHorseMule", ResourceLocation.parse("mule")); + map.put("EntityEvokerFangs", ResourceLocation.parse("evocation_fangs")); + map.put("EntityEvoker", ResourceLocation.parse("evocation_illager")); + map.put("EntityVex", ResourceLocation.parse("vex")); + map.put("EntityVindicator", ResourceLocation.parse("vindication_illager")); + map.put("EntityIllagerIllusioner", ResourceLocation.parse("illusion_illager")); + map.put("EntityMinecartCommandBlock", ResourceLocation.parse("commandblock_minecart")); + map.put("EntityBoat", ResourceLocation.parse("boat")); + map.put("EntityMinecartRideable", ResourceLocation.parse("minecart")); + map.put("EntityMinecartChest", ResourceLocation.parse("chest_minecart")); + map.put("EntityMinecartFurnace", ResourceLocation.parse("furnace_minecart")); + map.put("EntityMinecartTNT", ResourceLocation.parse("tnt_minecart")); + map.put("EntityMinecartHopper", ResourceLocation.parse("hopper_minecart")); + map.put("EntityMinecartMobSpawner", ResourceLocation.parse("spawner_minecart")); + map.put("EntityCreeper", ResourceLocation.parse("creeper")); + map.put("EntitySkeleton", ResourceLocation.parse("skeleton")); + map.put("EntitySpider", ResourceLocation.parse("spider")); + map.put("EntityGiantZombie", ResourceLocation.parse("giant")); + map.put("EntityZombie", ResourceLocation.parse("zombie")); + map.put("EntitySlime", ResourceLocation.parse("slime")); + map.put("EntityGhast", ResourceLocation.parse("ghast")); + map.put("EntityPigZombie", ResourceLocation.parse("zombie_pigman")); + map.put("EntityEnderman", ResourceLocation.parse("enderman")); + map.put("EntityCaveSpider", ResourceLocation.parse("cave_spider")); + map.put("EntitySilverfish", ResourceLocation.parse("silverfish")); + map.put("EntityBlaze", ResourceLocation.parse("blaze")); + map.put("EntityMagmaCube", ResourceLocation.parse("magma_cube")); + map.put("EntityEnderDragon", ResourceLocation.parse("ender_dragon")); + map.put("EntityWither", ResourceLocation.parse("wither")); + map.put("EntityBat", ResourceLocation.parse("bat")); + map.put("EntityWitch", ResourceLocation.parse("witch")); + map.put("EntityEndermite", ResourceLocation.parse("endermite")); + map.put("EntityGuardian", ResourceLocation.parse("guardian")); + map.put("EntityShulker", ResourceLocation.parse("shulker")); + map.put("EntityPig", ResourceLocation.parse("pig")); + map.put("EntitySheep", ResourceLocation.parse("sheep")); + map.put("EntityCow", ResourceLocation.parse("cow")); + map.put("EntityChicken", ResourceLocation.parse("chicken")); + map.put("EntitySquid", ResourceLocation.parse("squid")); + map.put("EntityWolf", ResourceLocation.parse("wolf")); + map.put("EntityMushroomCow", ResourceLocation.parse("mooshroom")); + map.put("EntitySnowman", ResourceLocation.parse("snowman")); + map.put("EntityOcelot", ResourceLocation.parse("ocelot")); + map.put("EntityIronGolem", ResourceLocation.parse("villager_golem")); + map.put("EntityHorse", ResourceLocation.parse("horse")); + map.put("EntityRabbit", ResourceLocation.parse("rabbit")); + map.put("EntityPolarBear", ResourceLocation.parse("polar_bear")); + map.put("EntityLlama", ResourceLocation.parse("llama")); + map.put("EntityLlamaSpit", ResourceLocation.parse("llama_spit")); + map.put("EntityParrot", ResourceLocation.parse("parrot")); + map.put("EntityVillager", ResourceLocation.parse("villager")); + map.put("EntityEnderCrystal", ResourceLocation.parse("ender_crystal")); + map.put("TileEntityFurnace", ResourceLocation.parse("furnace")); + map.put("TileEntityChest", ResourceLocation.parse("chest")); + map.put("TileEntityEnderChest", ResourceLocation.parse("ender_chest")); + map.put("TileEntityRecordPlayer", ResourceLocation.parse("jukebox")); + map.put("TileEntityDispenser", ResourceLocation.parse("dispenser")); + map.put("TileEntityDropper", ResourceLocation.parse("dropper")); + map.put("TileEntitySign", ResourceLocation.parse("sign")); + map.put("TileEntityMobSpawner", ResourceLocation.parse("mob_spawner")); + map.put("TileEntityNote", ResourceLocation.parse("noteblock")); + map.put("TileEntityPiston", ResourceLocation.parse("piston")); + map.put("TileEntityBrewingStand", ResourceLocation.parse("brewing_stand")); + map.put("TileEntityEnchantTable", ResourceLocation.parse("enchanting_table")); + map.put("TileEntityEnderPortal", ResourceLocation.parse("end_portal")); + map.put("TileEntityBeacon", ResourceLocation.parse("beacon")); + map.put("TileEntitySkull", ResourceLocation.parse("skull")); + map.put("TileEntityLightDetector", ResourceLocation.parse("daylight_detector")); + map.put("TileEntityHopper", ResourceLocation.parse("hopper")); + map.put("TileEntityComparator", ResourceLocation.parse("comparator")); + map.put("TileEntityFlowerPot", ResourceLocation.parse("flower_pot")); + map.put("TileEntityBanner", ResourceLocation.parse("banner")); + map.put("TileEntityStructure", ResourceLocation.parse("structure_block")); + map.put("TileEntityEndGateway", ResourceLocation.parse("end_gateway")); + map.put("TileEntityCommand", ResourceLocation.parse("command_block")); + map.put("TileEntityShulkerBox", ResourceLocation.parse("shulker_box")); + map.put("TileEntityBed", ResourceLocation.parse("bed")); + } + + private static ResourceLocation getKey(String type) { + final ResourceLocation key = OLD_ID_TO_KEY_MAP.get(type); + if (key == null) { + throw new IllegalArgumentException("Unknown mapping for " + type); + } + return key; + } + + private static void convertCompound(LegacyType type, CompoundTag cmp, String key, int sourceVer, int targetVer) { + cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer)); + } + + private static void convertItem(CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + if (nbttagcompound.contains(key, 10)) { + convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); + } + } + + private static void convertItems(CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + if (nbttagcompound.contains(key, 9)) { + ListTag nbttaglist = nbttagcompound.getList(key, 10); + + for (int j = 0; j < nbttaglist.size(); ++j) { + nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); + } + } + + } + + private static class DataConverterEquipment implements DataConverter { + + DataConverterEquipment() { + } + + public int getDataVersion() { + return 100; + } + + public CompoundTag convert(CompoundTag cmp) { + ListTag nbttaglist = cmp.getList("Equipment", 10); + ListTag nbttaglist1; + + if (!nbttaglist.isEmpty() && !cmp.contains("HandItems", 10)) { + nbttaglist1 = new ListTag(); + nbttaglist1.add(nbttaglist.get(0)); + nbttaglist1.add(new CompoundTag()); + cmp.put("HandItems", nbttaglist1); + } + + if (nbttaglist.size() > 1 && !cmp.contains("ArmorItem", 10)) { + nbttaglist1 = new ListTag(); + nbttaglist1.add(nbttaglist.get(1)); + nbttaglist1.add(nbttaglist.get(2)); + nbttaglist1.add(nbttaglist.get(3)); + nbttaglist1.add(nbttaglist.get(4)); + cmp.put("ArmorItems", nbttaglist1); + } + + cmp.remove("Equipment"); + if (cmp.contains("DropChances", 9)) { + nbttaglist1 = cmp.getList("DropChances", 5); + ListTag nbttaglist2; + + if (!cmp.contains("HandDropChances", 10)) { + nbttaglist2 = new ListTag(); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(0))); + nbttaglist2.add(FloatTag.valueOf(0.0F)); + cmp.put("HandDropChances", nbttaglist2); + } + + if (!cmp.contains("ArmorDropChances", 10)) { + nbttaglist2 = new ListTag(); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(1))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(2))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(3))); + nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloat(4))); + cmp.put("ArmorDropChances", nbttaglist2); + } + + cmp.remove("DropChances"); + } + + return cmp; + } + } + + private static class DataInspectorBlockEntity implements DataInspector { + + private static final Map b = Maps.newHashMap(); + private static final Map c = Maps.newHashMap(); + + DataInspectorBlockEntity() { + } + + @Nullable + private static String convertEntityId(int i, String s) { + String key = ResourceLocation.parse(s).toString(); + if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { + return DataInspectorBlockEntity.b.get(key); + } else { + return DataInspectorBlockEntity.c.get(key); + } + } + + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (!cmp.contains("tag", 10)) { + return cmp; + } else { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (nbttagcompound1.contains("BlockEntityTag", 10)) { + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + String s = cmp.getString("id"); + String s1 = convertEntityId(sourceVer, s); + boolean flag; + + if (s1 == null) { + // CraftBukkit - Remove unnecessary warning (occurs when deserializing a Shulker Box item) + // DataInspectorBlockEntity.a.warn("Unable to resolve BlockEntity for ItemInstance: {}", s); + flag = false; + } else { + flag = !nbttagcompound2.contains("id"); + nbttagcompound2.putString("id", s1); + } + + convert(LegacyType.BLOCK_ENTITY, nbttagcompound2, sourceVer, targetVer); + if (flag) { + nbttagcompound2.remove("id"); + } + } + + return cmp; + } + } + + static { + Map map = DataInspectorBlockEntity.b; + + map.put("minecraft:furnace", "Furnace"); + map.put("minecraft:lit_furnace", "Furnace"); + map.put("minecraft:chest", "Chest"); + map.put("minecraft:trapped_chest", "Chest"); + map.put("minecraft:ender_chest", "EnderChest"); + map.put("minecraft:jukebox", "RecordPlayer"); + map.put("minecraft:dispenser", "Trap"); + map.put("minecraft:dropper", "Dropper"); + map.put("minecraft:sign", "Sign"); + map.put("minecraft:mob_spawner", "MobSpawner"); + map.put("minecraft:noteblock", "Music"); + map.put("minecraft:brewing_stand", "Cauldron"); + map.put("minecraft:enhanting_table", "EnchantTable"); + map.put("minecraft:command_block", "CommandBlock"); + map.put("minecraft:beacon", "Beacon"); + map.put("minecraft:skull", "Skull"); + map.put("minecraft:daylight_detector", "DLDetector"); + map.put("minecraft:hopper", "Hopper"); + map.put("minecraft:banner", "Banner"); + map.put("minecraft:flower_pot", "FlowerPot"); + map.put("minecraft:repeating_command_block", "CommandBlock"); + map.put("minecraft:chain_command_block", "CommandBlock"); + map.put("minecraft:standing_sign", "Sign"); + map.put("minecraft:wall_sign", "Sign"); + map.put("minecraft:piston_head", "Piston"); + map.put("minecraft:daylight_detector_inverted", "DLDetector"); + map.put("minecraft:unpowered_comparator", "Comparator"); + map.put("minecraft:powered_comparator", "Comparator"); + map.put("minecraft:wall_banner", "Banner"); + map.put("minecraft:standing_banner", "Banner"); + map.put("minecraft:structure_block", "Structure"); + map.put("minecraft:end_portal", "Airportal"); + map.put("minecraft:end_gateway", "EndGateway"); + map.put("minecraft:shield", "Shield"); + map = DataInspectorBlockEntity.c; + map.put("minecraft:furnace", "minecraft:furnace"); + map.put("minecraft:lit_furnace", "minecraft:furnace"); + map.put("minecraft:chest", "minecraft:chest"); + map.put("minecraft:trapped_chest", "minecraft:chest"); + map.put("minecraft:ender_chest", "minecraft:enderchest"); + map.put("minecraft:jukebox", "minecraft:jukebox"); + map.put("minecraft:dispenser", "minecraft:dispenser"); + map.put("minecraft:dropper", "minecraft:dropper"); + map.put("minecraft:sign", "minecraft:sign"); + map.put("minecraft:mob_spawner", "minecraft:mob_spawner"); + map.put("minecraft:noteblock", "minecraft:noteblock"); + map.put("minecraft:brewing_stand", "minecraft:brewing_stand"); + map.put("minecraft:enhanting_table", "minecraft:enchanting_table"); + map.put("minecraft:command_block", "minecraft:command_block"); + map.put("minecraft:beacon", "minecraft:beacon"); + map.put("minecraft:skull", "minecraft:skull"); + map.put("minecraft:daylight_detector", "minecraft:daylight_detector"); + map.put("minecraft:hopper", "minecraft:hopper"); + map.put("minecraft:banner", "minecraft:banner"); + map.put("minecraft:flower_pot", "minecraft:flower_pot"); + map.put("minecraft:repeating_command_block", "minecraft:command_block"); + map.put("minecraft:chain_command_block", "minecraft:command_block"); + map.put("minecraft:shulker_box", "minecraft:shulker_box"); + map.put("minecraft:white_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:orange_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:magenta_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:light_blue_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:yellow_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:lime_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:pink_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:gray_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:silver_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:cyan_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:purple_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:blue_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:brown_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:green_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:red_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:black_shulker_box", "minecraft:shulker_box"); + map.put("minecraft:bed", "minecraft:bed"); + map.put("minecraft:standing_sign", "minecraft:sign"); + map.put("minecraft:wall_sign", "minecraft:sign"); + map.put("minecraft:piston_head", "minecraft:piston"); + map.put("minecraft:daylight_detector_inverted", "minecraft:daylight_detector"); + map.put("minecraft:unpowered_comparator", "minecraft:comparator"); + map.put("minecraft:powered_comparator", "minecraft:comparator"); + map.put("minecraft:wall_banner", "minecraft:banner"); + map.put("minecraft:standing_banner", "minecraft:banner"); + map.put("minecraft:structure_block", "minecraft:structure_block"); + map.put("minecraft:end_portal", "minecraft:end_portal"); + map.put("minecraft:end_gateway", "minecraft:end_gateway"); + map.put("minecraft:shield", "minecraft:shield"); + } + } + + private static class DataInspectorEntity implements DataInspector { + + DataInspectorEntity() { + } + + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (nbttagcompound1.contains("EntityTag", 10)) { + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + String s = cmp.getString("id"); + String s1; + + if ("minecraft:armor_stand".equals(s)) { + s1 = sourceVer < 515 ? "ArmorStand" : "minecraft:armor_stand"; + } else { + if (!"minecraft:spawn_egg".equals(s)) { + return cmp; + } + + s1 = nbttagcompound2.getString("id"); + } + + boolean flag; + + flag = !nbttagcompound2.contains("id", 8); + nbttagcompound2.putString("id", s1); + + convert(LegacyType.ENTITY, nbttagcompound2, sourceVer, targetVer); + if (flag) { + nbttagcompound2.remove("id"); + } + } + + return cmp; + } + } + + + private abstract static class DataInspectorTagged implements DataInspector { + + private final ResourceLocation key; + + DataInspectorTagged(String type) { + this.key = getKey(type); + } + + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (this.key.equals(ResourceLocation.parse(cmp.getString("id")))) { + cmp = this.inspectChecked(cmp, sourceVer, targetVer); + } + + return cmp; + } + + abstract CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer); + } + + private static class DataInspectorItemList extends DataInspectorTagged { + + private final String[] keys; + + DataInspectorItemList(String oclass, String... astring) { + super(oclass); + this.keys = astring; + } + + CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer) { + for (String s : this.keys) { + PaperweightDataConverters.convertItems(nbttagcompound, s, sourceVer, targetVer); + } + + return nbttagcompound; + } + } + + private static class DataInspectorItem extends DataInspectorTagged { + + private final String[] keys; + + DataInspectorItem(String oclass, String... astring) { + super(oclass); + this.keys = astring; + } + + CompoundTag inspectChecked(CompoundTag nbttagcompound, int sourceVer, int targetVer) { + for (String key : this.keys) { + PaperweightDataConverters.convertItem(nbttagcompound, key, sourceVer, targetVer); + } + + return nbttagcompound; + } + } + + private static class DataConverterMaterialId implements DataConverter { + + private static final String[] materials = new String[2268]; + + DataConverterMaterialId() { + } + + public int getDataVersion() { + return 102; + } + + public CompoundTag convert(CompoundTag cmp) { + if (cmp.contains("id", 99)) { + short short0 = cmp.getShort("id"); + + if (short0 > 0 && short0 < materials.length && materials[short0] != null) { + cmp.putString("id", materials[short0]); + } + } + + return cmp; + } + + static { + materials[1] = "minecraft:stone"; + materials[2] = "minecraft:grass"; + materials[3] = "minecraft:dirt"; + materials[4] = "minecraft:cobblestone"; + materials[5] = "minecraft:planks"; + materials[6] = "minecraft:sapling"; + materials[7] = "minecraft:bedrock"; + materials[8] = "minecraft:flowing_water"; + materials[9] = "minecraft:water"; + materials[10] = "minecraft:flowing_lava"; + materials[11] = "minecraft:lava"; + materials[12] = "minecraft:sand"; + materials[13] = "minecraft:gravel"; + materials[14] = "minecraft:gold_ore"; + materials[15] = "minecraft:iron_ore"; + materials[16] = "minecraft:coal_ore"; + materials[17] = "minecraft:log"; + materials[18] = "minecraft:leaves"; + materials[19] = "minecraft:sponge"; + materials[20] = "minecraft:glass"; + materials[21] = "minecraft:lapis_ore"; + materials[22] = "minecraft:lapis_block"; + materials[23] = "minecraft:dispenser"; + materials[24] = "minecraft:sandstone"; + materials[25] = "minecraft:noteblock"; + materials[27] = "minecraft:golden_rail"; + materials[28] = "minecraft:detector_rail"; + materials[29] = "minecraft:sticky_piston"; + materials[30] = "minecraft:web"; + materials[31] = "minecraft:tallgrass"; + materials[32] = "minecraft:deadbush"; + materials[33] = "minecraft:piston"; + materials[35] = "minecraft:wool"; + materials[37] = "minecraft:yellow_flower"; + materials[38] = "minecraft:red_flower"; + materials[39] = "minecraft:brown_mushroom"; + materials[40] = "minecraft:red_mushroom"; + materials[41] = "minecraft:gold_block"; + materials[42] = "minecraft:iron_block"; + materials[43] = "minecraft:double_stone_slab"; + materials[44] = "minecraft:stone_slab"; + materials[45] = "minecraft:brick_block"; + materials[46] = "minecraft:tnt"; + materials[47] = "minecraft:bookshelf"; + materials[48] = "minecraft:mossy_cobblestone"; + materials[49] = "minecraft:obsidian"; + materials[50] = "minecraft:torch"; + materials[51] = "minecraft:fire"; + materials[52] = "minecraft:mob_spawner"; + materials[53] = "minecraft:oak_stairs"; + materials[54] = "minecraft:chest"; + materials[56] = "minecraft:diamond_ore"; + materials[57] = "minecraft:diamond_block"; + materials[58] = "minecraft:crafting_table"; + materials[60] = "minecraft:farmland"; + materials[61] = "minecraft:furnace"; + materials[62] = "minecraft:lit_furnace"; + materials[65] = "minecraft:ladder"; + materials[66] = "minecraft:rail"; + materials[67] = "minecraft:stone_stairs"; + materials[69] = "minecraft:lever"; + materials[70] = "minecraft:stone_pressure_plate"; + materials[72] = "minecraft:wooden_pressure_plate"; + materials[73] = "minecraft:redstone_ore"; + materials[76] = "minecraft:redstone_torch"; + materials[77] = "minecraft:stone_button"; + materials[78] = "minecraft:snow_layer"; + materials[79] = "minecraft:ice"; + materials[80] = "minecraft:snow"; + materials[81] = "minecraft:cactus"; + materials[82] = "minecraft:clay"; + materials[84] = "minecraft:jukebox"; + materials[85] = "minecraft:fence"; + materials[86] = "minecraft:pumpkin"; + materials[87] = "minecraft:netherrack"; + materials[88] = "minecraft:soul_sand"; + materials[89] = "minecraft:glowstone"; + materials[90] = "minecraft:portal"; + materials[91] = "minecraft:lit_pumpkin"; + materials[95] = "minecraft:stained_glass"; + materials[96] = "minecraft:trapdoor"; + materials[97] = "minecraft:monster_egg"; + materials[98] = "minecraft:stonebrick"; + materials[99] = "minecraft:brown_mushroom_block"; + materials[100] = "minecraft:red_mushroom_block"; + materials[101] = "minecraft:iron_bars"; + materials[102] = "minecraft:glass_pane"; + materials[103] = "minecraft:melon_block"; + materials[106] = "minecraft:vine"; + materials[107] = "minecraft:fence_gate"; + materials[108] = "minecraft:brick_stairs"; + materials[109] = "minecraft:stone_brick_stairs"; + materials[110] = "minecraft:mycelium"; + materials[111] = "minecraft:waterlily"; + materials[112] = "minecraft:nether_brick"; + materials[113] = "minecraft:nether_brick_fence"; + materials[114] = "minecraft:nether_brick_stairs"; + materials[116] = "minecraft:enchanting_table"; + materials[119] = "minecraft:end_portal"; + materials[120] = "minecraft:end_portal_frame"; + materials[121] = "minecraft:end_stone"; + materials[122] = "minecraft:dragon_egg"; + materials[123] = "minecraft:redstone_lamp"; + materials[125] = "minecraft:double_wooden_slab"; + materials[126] = "minecraft:wooden_slab"; + materials[127] = "minecraft:cocoa"; + materials[128] = "minecraft:sandstone_stairs"; + materials[129] = "minecraft:emerald_ore"; + materials[130] = "minecraft:ender_chest"; + materials[131] = "minecraft:tripwire_hook"; + materials[133] = "minecraft:emerald_block"; + materials[134] = "minecraft:spruce_stairs"; + materials[135] = "minecraft:birch_stairs"; + materials[136] = "minecraft:jungle_stairs"; + materials[137] = "minecraft:command_block"; + materials[138] = "minecraft:beacon"; + materials[139] = "minecraft:cobblestone_wall"; + materials[141] = "minecraft:carrots"; + materials[142] = "minecraft:potatoes"; + materials[143] = "minecraft:wooden_button"; + materials[145] = "minecraft:anvil"; + materials[146] = "minecraft:trapped_chest"; + materials[147] = "minecraft:light_weighted_pressure_plate"; + materials[148] = "minecraft:heavy_weighted_pressure_plate"; + materials[151] = "minecraft:daylight_detector"; + materials[152] = "minecraft:redstone_block"; + materials[153] = "minecraft:quartz_ore"; + materials[154] = "minecraft:hopper"; + materials[155] = "minecraft:quartz_block"; + materials[156] = "minecraft:quartz_stairs"; + materials[157] = "minecraft:activator_rail"; + materials[158] = "minecraft:dropper"; + materials[159] = "minecraft:stained_hardened_clay"; + materials[160] = "minecraft:stained_glass_pane"; + materials[161] = "minecraft:leaves2"; + materials[162] = "minecraft:log2"; + materials[163] = "minecraft:acacia_stairs"; + materials[164] = "minecraft:dark_oak_stairs"; + materials[170] = "minecraft:hay_block"; + materials[171] = "minecraft:carpet"; + materials[172] = "minecraft:hardened_clay"; + materials[173] = "minecraft:coal_block"; + materials[174] = "minecraft:packed_ice"; + materials[175] = "minecraft:double_plant"; + materials[256] = "minecraft:iron_shovel"; + materials[257] = "minecraft:iron_pickaxe"; + materials[258] = "minecraft:iron_axe"; + materials[259] = "minecraft:flint_and_steel"; + materials[260] = "minecraft:apple"; + materials[261] = "minecraft:bow"; + materials[262] = "minecraft:arrow"; + materials[263] = "minecraft:coal"; + materials[264] = "minecraft:diamond"; + materials[265] = "minecraft:iron_ingot"; + materials[266] = "minecraft:gold_ingot"; + materials[267] = "minecraft:iron_sword"; + materials[268] = "minecraft:wooden_sword"; + materials[269] = "minecraft:wooden_shovel"; + materials[270] = "minecraft:wooden_pickaxe"; + materials[271] = "minecraft:wooden_axe"; + materials[272] = "minecraft:stone_sword"; + materials[273] = "minecraft:stone_shovel"; + materials[274] = "minecraft:stone_pickaxe"; + materials[275] = "minecraft:stone_axe"; + materials[276] = "minecraft:diamond_sword"; + materials[277] = "minecraft:diamond_shovel"; + materials[278] = "minecraft:diamond_pickaxe"; + materials[279] = "minecraft:diamond_axe"; + materials[280] = "minecraft:stick"; + materials[281] = "minecraft:bowl"; + materials[282] = "minecraft:mushroom_stew"; + materials[283] = "minecraft:golden_sword"; + materials[284] = "minecraft:golden_shovel"; + materials[285] = "minecraft:golden_pickaxe"; + materials[286] = "minecraft:golden_axe"; + materials[287] = "minecraft:string"; + materials[288] = "minecraft:feather"; + materials[289] = "minecraft:gunpowder"; + materials[290] = "minecraft:wooden_hoe"; + materials[291] = "minecraft:stone_hoe"; + materials[292] = "minecraft:iron_hoe"; + materials[293] = "minecraft:diamond_hoe"; + materials[294] = "minecraft:golden_hoe"; + materials[295] = "minecraft:wheat_seeds"; + materials[296] = "minecraft:wheat"; + materials[297] = "minecraft:bread"; + materials[298] = "minecraft:leather_helmet"; + materials[299] = "minecraft:leather_chestplate"; + materials[300] = "minecraft:leather_leggings"; + materials[301] = "minecraft:leather_boots"; + materials[302] = "minecraft:chainmail_helmet"; + materials[303] = "minecraft:chainmail_chestplate"; + materials[304] = "minecraft:chainmail_leggings"; + materials[305] = "minecraft:chainmail_boots"; + materials[306] = "minecraft:iron_helmet"; + materials[307] = "minecraft:iron_chestplate"; + materials[308] = "minecraft:iron_leggings"; + materials[309] = "minecraft:iron_boots"; + materials[310] = "minecraft:diamond_helmet"; + materials[311] = "minecraft:diamond_chestplate"; + materials[312] = "minecraft:diamond_leggings"; + materials[313] = "minecraft:diamond_boots"; + materials[314] = "minecraft:golden_helmet"; + materials[315] = "minecraft:golden_chestplate"; + materials[316] = "minecraft:golden_leggings"; + materials[317] = "minecraft:golden_boots"; + materials[318] = "minecraft:flint"; + materials[319] = "minecraft:porkchop"; + materials[320] = "minecraft:cooked_porkchop"; + materials[321] = "minecraft:painting"; + materials[322] = "minecraft:golden_apple"; + materials[323] = "minecraft:sign"; + materials[324] = "minecraft:wooden_door"; + materials[325] = "minecraft:bucket"; + materials[326] = "minecraft:water_bucket"; + materials[327] = "minecraft:lava_bucket"; + materials[328] = "minecraft:minecart"; + materials[329] = "minecraft:saddle"; + materials[330] = "minecraft:iron_door"; + materials[331] = "minecraft:redstone"; + materials[332] = "minecraft:snowball"; + materials[333] = "minecraft:boat"; + materials[334] = "minecraft:leather"; + materials[335] = "minecraft:milk_bucket"; + materials[336] = "minecraft:brick"; + materials[337] = "minecraft:clay_ball"; + materials[338] = "minecraft:reeds"; + materials[339] = "minecraft:paper"; + materials[340] = "minecraft:book"; + materials[341] = "minecraft:slime_ball"; + materials[342] = "minecraft:chest_minecart"; + materials[343] = "minecraft:furnace_minecart"; + materials[344] = "minecraft:egg"; + materials[345] = "minecraft:compass"; + materials[346] = "minecraft:fishing_rod"; + materials[347] = "minecraft:clock"; + materials[348] = "minecraft:glowstone_dust"; + materials[349] = "minecraft:fish"; + materials[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish + materials[351] = "minecraft:dye"; + materials[352] = "minecraft:bone"; + materials[353] = "minecraft:sugar"; + materials[354] = "minecraft:cake"; + materials[355] = "minecraft:bed"; + materials[356] = "minecraft:repeater"; + materials[357] = "minecraft:cookie"; + materials[358] = "minecraft:filled_map"; + materials[359] = "minecraft:shears"; + materials[360] = "minecraft:melon"; + materials[361] = "minecraft:pumpkin_seeds"; + materials[362] = "minecraft:melon_seeds"; + materials[363] = "minecraft:beef"; + materials[364] = "minecraft:cooked_beef"; + materials[365] = "minecraft:chicken"; + materials[366] = "minecraft:cooked_chicken"; + materials[367] = "minecraft:rotten_flesh"; + materials[368] = "minecraft:ender_pearl"; + materials[369] = "minecraft:blaze_rod"; + materials[370] = "minecraft:ghast_tear"; + materials[371] = "minecraft:gold_nugget"; + materials[372] = "minecraft:nether_wart"; + materials[373] = "minecraft:potion"; + materials[374] = "minecraft:glass_bottle"; + materials[375] = "minecraft:spider_eye"; + materials[376] = "minecraft:fermented_spider_eye"; + materials[377] = "minecraft:blaze_powder"; + materials[378] = "minecraft:magma_cream"; + materials[379] = "minecraft:brewing_stand"; + materials[380] = "minecraft:cauldron"; + materials[381] = "minecraft:ender_eye"; + materials[382] = "minecraft:speckled_melon"; + materials[383] = "minecraft:spawn_egg"; + materials[384] = "minecraft:experience_bottle"; + materials[385] = "minecraft:fire_charge"; + materials[386] = "minecraft:writable_book"; + materials[387] = "minecraft:written_book"; + materials[388] = "minecraft:emerald"; + materials[389] = "minecraft:item_frame"; + materials[390] = "minecraft:flower_pot"; + materials[391] = "minecraft:carrot"; + materials[392] = "minecraft:potato"; + materials[393] = "minecraft:baked_potato"; + materials[394] = "minecraft:poisonous_potato"; + materials[395] = "minecraft:map"; + materials[396] = "minecraft:golden_carrot"; + materials[397] = "minecraft:skull"; + materials[398] = "minecraft:carrot_on_a_stick"; + materials[399] = "minecraft:nether_star"; + materials[400] = "minecraft:pumpkin_pie"; + materials[401] = "minecraft:fireworks"; + materials[402] = "minecraft:firework_charge"; + materials[403] = "minecraft:enchanted_book"; + materials[404] = "minecraft:comparator"; + materials[405] = "minecraft:netherbrick"; + materials[406] = "minecraft:quartz"; + materials[407] = "minecraft:tnt_minecart"; + materials[408] = "minecraft:hopper_minecart"; + materials[417] = "minecraft:iron_horse_armor"; + materials[418] = "minecraft:golden_horse_armor"; + materials[419] = "minecraft:diamond_horse_armor"; + materials[420] = "minecraft:lead"; + materials[421] = "minecraft:name_tag"; + materials[422] = "minecraft:command_block_minecart"; + materials[2256] = "minecraft:record_13"; + materials[2257] = "minecraft:record_cat"; + materials[2258] = "minecraft:record_blocks"; + materials[2259] = "minecraft:record_chirp"; + materials[2260] = "minecraft:record_far"; + materials[2261] = "minecraft:record_mall"; + materials[2262] = "minecraft:record_mellohi"; + materials[2263] = "minecraft:record_stal"; + materials[2264] = "minecraft:record_strad"; + materials[2265] = "minecraft:record_ward"; + materials[2266] = "minecraft:record_11"; + materials[2267] = "minecraft:record_wait"; + // Paper start + materials[409] = "minecraft:prismarine_shard"; + materials[410] = "minecraft:prismarine_crystals"; + materials[411] = "minecraft:rabbit"; + materials[412] = "minecraft:cooked_rabbit"; + materials[413] = "minecraft:rabbit_stew"; + materials[414] = "minecraft:rabbit_foot"; + materials[415] = "minecraft:rabbit_hide"; + materials[416] = "minecraft:armor_stand"; + materials[423] = "minecraft:mutton"; + materials[424] = "minecraft:cooked_mutton"; + materials[425] = "minecraft:banner"; + materials[426] = "minecraft:end_crystal"; + materials[427] = "minecraft:spruce_door"; + materials[428] = "minecraft:birch_door"; + materials[429] = "minecraft:jungle_door"; + materials[430] = "minecraft:acacia_door"; + materials[431] = "minecraft:dark_oak_door"; + materials[432] = "minecraft:chorus_fruit"; + materials[433] = "minecraft:chorus_fruit_popped"; + materials[434] = "minecraft:beetroot"; + materials[435] = "minecraft:beetroot_seeds"; + materials[436] = "minecraft:beetroot_soup"; + materials[437] = "minecraft:dragon_breath"; + materials[438] = "minecraft:splash_potion"; + materials[439] = "minecraft:spectral_arrow"; + materials[440] = "minecraft:tipped_arrow"; + materials[441] = "minecraft:lingering_potion"; + materials[442] = "minecraft:shield"; + materials[443] = "minecraft:elytra"; + materials[444] = "minecraft:spruce_boat"; + materials[445] = "minecraft:birch_boat"; + materials[446] = "minecraft:jungle_boat"; + materials[447] = "minecraft:acacia_boat"; + materials[448] = "minecraft:dark_oak_boat"; + materials[449] = "minecraft:totem_of_undying"; + materials[450] = "minecraft:shulker_shell"; + materials[452] = "minecraft:iron_nugget"; + materials[453] = "minecraft:knowledge_book"; + // Paper end + } + } + + private static class DataConverterArmorStand implements DataConverter { + + DataConverterArmorStand() { + } + + public int getDataVersion() { + return 147; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("ArmorStand".equals(cmp.getString("id")) && cmp.getBoolean("Silent") && !cmp.getBoolean("Marker")) { + cmp.remove("Silent"); + } + + return cmp; + } + } + + private static class DataConverterBanner implements DataConverter { + + DataConverterBanner() { + } + + public int getDataVersion() { + return 804; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:banner".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (nbttagcompound1.contains("BlockEntityTag", 10)) { + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + + if (nbttagcompound2.contains("Base", 99)) { + cmp.putShort("Damage", (short) (nbttagcompound2.getShort("Base") & 15)); + if (nbttagcompound1.contains("display", 10)) { + CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); + + if (nbttagcompound3.contains("Lore", 9)) { + ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); + + if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0))) { + return cmp; + } + } + } + + nbttagcompound2.remove("Base"); + if (nbttagcompound2.isEmpty()) { + nbttagcompound1.remove("BlockEntityTag"); + } + + if (nbttagcompound1.isEmpty()) { + cmp.remove("tag"); + } + } + } + } + + return cmp; + } + } + + private static class DataConverterPotionId implements DataConverter { + + private static final String[] potions = new String[128]; + + DataConverterPotionId() { + } + + public int getDataVersion() { + return 102; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:potion".equals(cmp.getString("id"))) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + short short0 = cmp.getShort("Damage"); + + if (!nbttagcompound1.contains("Potion", 8)) { + String s = DataConverterPotionId.potions[short0 & 127]; + + nbttagcompound1.putString("Potion", s == null ? "minecraft:water" : s); + cmp.put("tag", nbttagcompound1); + if ((short0 & 16384) == 16384) { + cmp.putString("id", "minecraft:splash_potion"); + } + } + + if (short0 != 0) { + cmp.putShort("Damage", (short) 0); + } + } + + return cmp; + } + + static { + DataConverterPotionId.potions[0] = "minecraft:water"; + DataConverterPotionId.potions[1] = "minecraft:regeneration"; + DataConverterPotionId.potions[2] = "minecraft:swiftness"; + DataConverterPotionId.potions[3] = "minecraft:fire_resistance"; + DataConverterPotionId.potions[4] = "minecraft:poison"; + DataConverterPotionId.potions[5] = "minecraft:healing"; + DataConverterPotionId.potions[6] = "minecraft:night_vision"; + DataConverterPotionId.potions[7] = null; + DataConverterPotionId.potions[8] = "minecraft:weakness"; + DataConverterPotionId.potions[9] = "minecraft:strength"; + DataConverterPotionId.potions[10] = "minecraft:slowness"; + DataConverterPotionId.potions[11] = "minecraft:leaping"; + DataConverterPotionId.potions[12] = "minecraft:harming"; + DataConverterPotionId.potions[13] = "minecraft:water_breathing"; + DataConverterPotionId.potions[14] = "minecraft:invisibility"; + DataConverterPotionId.potions[15] = null; + DataConverterPotionId.potions[16] = "minecraft:awkward"; + DataConverterPotionId.potions[17] = "minecraft:regeneration"; + DataConverterPotionId.potions[18] = "minecraft:swiftness"; + DataConverterPotionId.potions[19] = "minecraft:fire_resistance"; + DataConverterPotionId.potions[20] = "minecraft:poison"; + DataConverterPotionId.potions[21] = "minecraft:healing"; + DataConverterPotionId.potions[22] = "minecraft:night_vision"; + DataConverterPotionId.potions[23] = null; + DataConverterPotionId.potions[24] = "minecraft:weakness"; + DataConverterPotionId.potions[25] = "minecraft:strength"; + DataConverterPotionId.potions[26] = "minecraft:slowness"; + DataConverterPotionId.potions[27] = "minecraft:leaping"; + DataConverterPotionId.potions[28] = "minecraft:harming"; + DataConverterPotionId.potions[29] = "minecraft:water_breathing"; + DataConverterPotionId.potions[30] = "minecraft:invisibility"; + DataConverterPotionId.potions[31] = null; + DataConverterPotionId.potions[32] = "minecraft:thick"; + DataConverterPotionId.potions[33] = "minecraft:strong_regeneration"; + DataConverterPotionId.potions[34] = "minecraft:strong_swiftness"; + DataConverterPotionId.potions[35] = "minecraft:fire_resistance"; + DataConverterPotionId.potions[36] = "minecraft:strong_poison"; + DataConverterPotionId.potions[37] = "minecraft:strong_healing"; + DataConverterPotionId.potions[38] = "minecraft:night_vision"; + DataConverterPotionId.potions[39] = null; + DataConverterPotionId.potions[40] = "minecraft:weakness"; + DataConverterPotionId.potions[41] = "minecraft:strong_strength"; + DataConverterPotionId.potions[42] = "minecraft:slowness"; + DataConverterPotionId.potions[43] = "minecraft:strong_leaping"; + DataConverterPotionId.potions[44] = "minecraft:strong_harming"; + DataConverterPotionId.potions[45] = "minecraft:water_breathing"; + DataConverterPotionId.potions[46] = "minecraft:invisibility"; + DataConverterPotionId.potions[47] = null; + DataConverterPotionId.potions[48] = null; + DataConverterPotionId.potions[49] = "minecraft:strong_regeneration"; + DataConverterPotionId.potions[50] = "minecraft:strong_swiftness"; + DataConverterPotionId.potions[51] = "minecraft:fire_resistance"; + DataConverterPotionId.potions[52] = "minecraft:strong_poison"; + DataConverterPotionId.potions[53] = "minecraft:strong_healing"; + DataConverterPotionId.potions[54] = "minecraft:night_vision"; + DataConverterPotionId.potions[55] = null; + DataConverterPotionId.potions[56] = "minecraft:weakness"; + DataConverterPotionId.potions[57] = "minecraft:strong_strength"; + DataConverterPotionId.potions[58] = "minecraft:slowness"; + DataConverterPotionId.potions[59] = "minecraft:strong_leaping"; + DataConverterPotionId.potions[60] = "minecraft:strong_harming"; + DataConverterPotionId.potions[61] = "minecraft:water_breathing"; + DataConverterPotionId.potions[62] = "minecraft:invisibility"; + DataConverterPotionId.potions[63] = null; + DataConverterPotionId.potions[64] = "minecraft:mundane"; + DataConverterPotionId.potions[65] = "minecraft:long_regeneration"; + DataConverterPotionId.potions[66] = "minecraft:long_swiftness"; + DataConverterPotionId.potions[67] = "minecraft:long_fire_resistance"; + DataConverterPotionId.potions[68] = "minecraft:long_poison"; + DataConverterPotionId.potions[69] = "minecraft:healing"; + DataConverterPotionId.potions[70] = "minecraft:long_night_vision"; + DataConverterPotionId.potions[71] = null; + DataConverterPotionId.potions[72] = "minecraft:long_weakness"; + DataConverterPotionId.potions[73] = "minecraft:long_strength"; + DataConverterPotionId.potions[74] = "minecraft:long_slowness"; + DataConverterPotionId.potions[75] = "minecraft:long_leaping"; + DataConverterPotionId.potions[76] = "minecraft:harming"; + DataConverterPotionId.potions[77] = "minecraft:long_water_breathing"; + DataConverterPotionId.potions[78] = "minecraft:long_invisibility"; + DataConverterPotionId.potions[79] = null; + DataConverterPotionId.potions[80] = "minecraft:awkward"; + DataConverterPotionId.potions[81] = "minecraft:long_regeneration"; + DataConverterPotionId.potions[82] = "minecraft:long_swiftness"; + DataConverterPotionId.potions[83] = "minecraft:long_fire_resistance"; + DataConverterPotionId.potions[84] = "minecraft:long_poison"; + DataConverterPotionId.potions[85] = "minecraft:healing"; + DataConverterPotionId.potions[86] = "minecraft:long_night_vision"; + DataConverterPotionId.potions[87] = null; + DataConverterPotionId.potions[88] = "minecraft:long_weakness"; + DataConverterPotionId.potions[89] = "minecraft:long_strength"; + DataConverterPotionId.potions[90] = "minecraft:long_slowness"; + DataConverterPotionId.potions[91] = "minecraft:long_leaping"; + DataConverterPotionId.potions[92] = "minecraft:harming"; + DataConverterPotionId.potions[93] = "minecraft:long_water_breathing"; + DataConverterPotionId.potions[94] = "minecraft:long_invisibility"; + DataConverterPotionId.potions[95] = null; + DataConverterPotionId.potions[96] = "minecraft:thick"; + DataConverterPotionId.potions[97] = "minecraft:regeneration"; + DataConverterPotionId.potions[98] = "minecraft:swiftness"; + DataConverterPotionId.potions[99] = "minecraft:long_fire_resistance"; + DataConverterPotionId.potions[100] = "minecraft:poison"; + DataConverterPotionId.potions[101] = "minecraft:strong_healing"; + DataConverterPotionId.potions[102] = "minecraft:long_night_vision"; + DataConverterPotionId.potions[103] = null; + DataConverterPotionId.potions[104] = "minecraft:long_weakness"; + DataConverterPotionId.potions[105] = "minecraft:strength"; + DataConverterPotionId.potions[106] = "minecraft:long_slowness"; + DataConverterPotionId.potions[107] = "minecraft:leaping"; + DataConverterPotionId.potions[108] = "minecraft:strong_harming"; + DataConverterPotionId.potions[109] = "minecraft:long_water_breathing"; + DataConverterPotionId.potions[110] = "minecraft:long_invisibility"; + DataConverterPotionId.potions[111] = null; + DataConverterPotionId.potions[112] = null; + DataConverterPotionId.potions[113] = "minecraft:regeneration"; + DataConverterPotionId.potions[114] = "minecraft:swiftness"; + DataConverterPotionId.potions[115] = "minecraft:long_fire_resistance"; + DataConverterPotionId.potions[116] = "minecraft:poison"; + DataConverterPotionId.potions[117] = "minecraft:strong_healing"; + DataConverterPotionId.potions[118] = "minecraft:long_night_vision"; + DataConverterPotionId.potions[119] = null; + DataConverterPotionId.potions[120] = "minecraft:long_weakness"; + DataConverterPotionId.potions[121] = "minecraft:strength"; + DataConverterPotionId.potions[122] = "minecraft:long_slowness"; + DataConverterPotionId.potions[123] = "minecraft:leaping"; + DataConverterPotionId.potions[124] = "minecraft:strong_harming"; + DataConverterPotionId.potions[125] = "minecraft:long_water_breathing"; + DataConverterPotionId.potions[126] = "minecraft:long_invisibility"; + DataConverterPotionId.potions[127] = null; + } + } + + private static class DataConverterSpawnEgg implements DataConverter { + + private static final String[] eggs = new String[256]; + + DataConverterSpawnEgg() { + } + + public int getDataVersion() { + return 105; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + short short0 = cmp.getShort("Damage"); + + if (!nbttagcompound2.contains("id", 8)) { + String s = DataConverterSpawnEgg.eggs[short0 & 255]; + + if (s != null) { + nbttagcompound2.putString("id", s); + nbttagcompound1.put("EntityTag", nbttagcompound2); + cmp.put("tag", nbttagcompound1); + } + } + + if (short0 != 0) { + cmp.putShort("Damage", (short) 0); + } + } + + return cmp; + } + + static { + + DataConverterSpawnEgg.eggs[1] = "Item"; + DataConverterSpawnEgg.eggs[2] = "XPOrb"; + DataConverterSpawnEgg.eggs[7] = "ThrownEgg"; + DataConverterSpawnEgg.eggs[8] = "LeashKnot"; + DataConverterSpawnEgg.eggs[9] = "Painting"; + DataConverterSpawnEgg.eggs[10] = "Arrow"; + DataConverterSpawnEgg.eggs[11] = "Snowball"; + DataConverterSpawnEgg.eggs[12] = "Fireball"; + DataConverterSpawnEgg.eggs[13] = "SmallFireball"; + DataConverterSpawnEgg.eggs[14] = "ThrownEnderpearl"; + DataConverterSpawnEgg.eggs[15] = "EyeOfEnderSignal"; + DataConverterSpawnEgg.eggs[16] = "ThrownPotion"; + DataConverterSpawnEgg.eggs[17] = "ThrownExpBottle"; + DataConverterSpawnEgg.eggs[18] = "ItemFrame"; + DataConverterSpawnEgg.eggs[19] = "WitherSkull"; + DataConverterSpawnEgg.eggs[20] = "PrimedTnt"; + DataConverterSpawnEgg.eggs[21] = "FallingSand"; + DataConverterSpawnEgg.eggs[22] = "FireworksRocketEntity"; + DataConverterSpawnEgg.eggs[23] = "TippedArrow"; + DataConverterSpawnEgg.eggs[24] = "SpectralArrow"; + DataConverterSpawnEgg.eggs[25] = "ShulkerBullet"; + DataConverterSpawnEgg.eggs[26] = "DragonFireball"; + DataConverterSpawnEgg.eggs[30] = "ArmorStand"; + DataConverterSpawnEgg.eggs[41] = "Boat"; + DataConverterSpawnEgg.eggs[42] = "MinecartRideable"; + DataConverterSpawnEgg.eggs[43] = "MinecartChest"; + DataConverterSpawnEgg.eggs[44] = "MinecartFurnace"; + DataConverterSpawnEgg.eggs[45] = "MinecartTNT"; + DataConverterSpawnEgg.eggs[46] = "MinecartHopper"; + DataConverterSpawnEgg.eggs[47] = "MinecartSpawner"; + DataConverterSpawnEgg.eggs[40] = "MinecartCommandBlock"; + DataConverterSpawnEgg.eggs[48] = "Mob"; + DataConverterSpawnEgg.eggs[49] = "Monster"; + DataConverterSpawnEgg.eggs[50] = "Creeper"; + DataConverterSpawnEgg.eggs[51] = "Skeleton"; + DataConverterSpawnEgg.eggs[52] = "Spider"; + DataConverterSpawnEgg.eggs[53] = "Giant"; + DataConverterSpawnEgg.eggs[54] = "Zombie"; + DataConverterSpawnEgg.eggs[55] = "Slime"; + DataConverterSpawnEgg.eggs[56] = "Ghast"; + DataConverterSpawnEgg.eggs[57] = "PigZombie"; + DataConverterSpawnEgg.eggs[58] = "Enderman"; + DataConverterSpawnEgg.eggs[59] = "CaveSpider"; + DataConverterSpawnEgg.eggs[60] = "Silverfish"; + DataConverterSpawnEgg.eggs[61] = "Blaze"; + DataConverterSpawnEgg.eggs[62] = "LavaSlime"; + DataConverterSpawnEgg.eggs[63] = "EnderDragon"; + DataConverterSpawnEgg.eggs[64] = "WitherBoss"; + DataConverterSpawnEgg.eggs[65] = "Bat"; + DataConverterSpawnEgg.eggs[66] = "Witch"; + DataConverterSpawnEgg.eggs[67] = "Endermite"; + DataConverterSpawnEgg.eggs[68] = "Guardian"; + DataConverterSpawnEgg.eggs[69] = "Shulker"; + DataConverterSpawnEgg.eggs[90] = "Pig"; + DataConverterSpawnEgg.eggs[91] = "Sheep"; + DataConverterSpawnEgg.eggs[92] = "Cow"; + DataConverterSpawnEgg.eggs[93] = "Chicken"; + DataConverterSpawnEgg.eggs[94] = "Squid"; + DataConverterSpawnEgg.eggs[95] = "Wolf"; + DataConverterSpawnEgg.eggs[96] = "MushroomCow"; + DataConverterSpawnEgg.eggs[97] = "SnowMan"; + DataConverterSpawnEgg.eggs[98] = "Ozelot"; + DataConverterSpawnEgg.eggs[99] = "VillagerGolem"; + DataConverterSpawnEgg.eggs[100] = "EntityHorse"; + DataConverterSpawnEgg.eggs[101] = "Rabbit"; + DataConverterSpawnEgg.eggs[120] = "Villager"; + DataConverterSpawnEgg.eggs[200] = "EnderCrystal"; + } + } + + private static class DataConverterMinecart implements DataConverter { + + private static final List a = Lists.newArrayList("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock"); + + DataConverterMinecart() { + } + + public int getDataVersion() { + return 106; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("Minecart".equals(cmp.getString("id"))) { + String s = "MinecartRideable"; + int i = cmp.getInt("Type"); + + if (i > 0 && i < DataConverterMinecart.a.size()) { + s = DataConverterMinecart.a.get(i); + } + + cmp.putString("id", s); + cmp.remove("Type"); + } + + return cmp; + } + } + + private static class DataConverterMobSpawner implements DataConverter { + + DataConverterMobSpawner() { + } + + public int getDataVersion() { + return 107; + } + + public CompoundTag convert(CompoundTag cmp) { + if (!"MobSpawner".equals(cmp.getString("id"))) { + return cmp; + } else { + if (cmp.contains("EntityId", 8)) { + String s = cmp.getString("EntityId"); + CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); + + nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); + cmp.put("SpawnData", nbttagcompound1); + cmp.remove("EntityId"); + } + + if (cmp.contains("SpawnPotentials", 9)) { + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); + + for (int i = 0; i < nbttaglist.size(); ++i) { + CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); + + if (nbttagcompound2.contains("Type", 8)) { + CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); + + nbttagcompound3.putString("id", nbttagcompound2.getString("Type")); + nbttagcompound2.put("Entity", nbttagcompound3); + nbttagcompound2.remove("Type"); + nbttagcompound2.remove("Properties"); + } + } + } + + return cmp; + } + } + } + + private static class DataConverterUUID implements DataConverter { + + DataConverterUUID() { + } + + public int getDataVersion() { + return 108; + } + + public CompoundTag convert(CompoundTag cmp) { + if (cmp.contains("UUID", 8)) { + cmp.putUUID("UUID", UUID.fromString(cmp.getString("UUID"))); + } + + return cmp; + } + } + + private static class DataConverterHealth implements DataConverter { + + private static final Set a = Sets.newHashSet("ArmorStand", "Bat", "Blaze", "CaveSpider", "Chicken", "Cow", "Creeper", "EnderDragon", "Enderman", "Endermite", "EntityHorse", "Ghast", "Giant", "Guardian", "LavaSlime", "MushroomCow", "Ozelot", "Pig", "PigZombie", "Rabbit", "Sheep", "Shulker", "Silverfish", "Skeleton", "Slime", "SnowMan", "Spider", "Squid", "Villager", "VillagerGolem", "Witch", "WitherBoss", "Wolf", "Zombie"); + + DataConverterHealth() { + } + + public int getDataVersion() { + return 109; + } + + public CompoundTag convert(CompoundTag cmp) { + if (DataConverterHealth.a.contains(cmp.getString("id"))) { + float f; + + if (cmp.contains("HealF", 99)) { + f = cmp.getFloat("HealF"); + cmp.remove("HealF"); + } else { + if (!cmp.contains("Health", 99)) { + return cmp; + } + + f = cmp.getFloat("Health"); + } + + cmp.putFloat("Health", f); + } + + return cmp; + } + } + + private static class DataConverterSaddle implements DataConverter { + + DataConverterSaddle() { + } + + public int getDataVersion() { + return 110; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("EntityHorse".equals(cmp.getString("id")) && !cmp.contains("SaddleItem", 10) && cmp.getBoolean("Saddle")) { + CompoundTag nbttagcompound1 = new CompoundTag(); + + nbttagcompound1.putString("id", "minecraft:saddle"); + nbttagcompound1.putByte("Count", (byte) 1); + nbttagcompound1.putShort("Damage", (short) 0); + cmp.put("SaddleItem", nbttagcompound1); + cmp.remove("Saddle"); + } + + return cmp; + } + } + + private static class DataConverterHanging implements DataConverter { + + DataConverterHanging() { + } + + public int getDataVersion() { + return 111; + } + + public CompoundTag convert(CompoundTag cmp) { + String s = cmp.getString("id"); + boolean flag = "Painting".equals(s); + boolean flag1 = "ItemFrame".equals(s); + + if ((flag || flag1) && !cmp.contains("Facing", 99)) { + Direction enumdirection; + + if (cmp.contains("Direction", 99)) { + enumdirection = Direction.from2DDataValue(cmp.getByte("Direction")); + cmp.putInt("TileX", cmp.getInt("TileX") + enumdirection.getStepX()); + cmp.putInt("TileY", cmp.getInt("TileY") + enumdirection.getStepY()); + cmp.putInt("TileZ", cmp.getInt("TileZ") + enumdirection.getStepZ()); + cmp.remove("Direction"); + if (flag1 && cmp.contains("ItemRotation", 99)) { + cmp.putByte("ItemRotation", (byte) (cmp.getByte("ItemRotation") * 2)); + } + } else { + enumdirection = Direction.from2DDataValue(cmp.getByte("Dir")); + cmp.remove("Dir"); + } + + cmp.putByte("Facing", (byte) enumdirection.get2DDataValue()); + } + + return cmp; + } + } + + private static class DataConverterDropChances implements DataConverter { + + DataConverterDropChances() { + } + + public int getDataVersion() { + return 113; + } + + public CompoundTag convert(CompoundTag cmp) { + ListTag nbttaglist; + + if (cmp.contains("HandDropChances", 9)) { + nbttaglist = cmp.getList("HandDropChances", 5); + if (nbttaglist.size() == 2 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F) { + cmp.remove("HandDropChances"); + } + } + + if (cmp.contains("ArmorDropChances", 9)) { + nbttaglist = cmp.getList("ArmorDropChances", 5); + if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { + cmp.remove("ArmorDropChances"); + } + } + + return cmp; + } + } + + private static class DataConverterRiding implements DataConverter { + + DataConverterRiding() { + } + + public int getDataVersion() { + return 135; + } + + public CompoundTag convert(CompoundTag cmp) { + while (cmp.contains("Riding", 10)) { + CompoundTag nbttagcompound1 = this.b(cmp); + + this.convert(cmp, nbttagcompound1); + cmp = nbttagcompound1; + } + + return cmp; + } + + protected void convert(CompoundTag nbttagcompound, CompoundTag nbttagcompound1) { + ListTag nbttaglist = new ListTag(); + + nbttaglist.add(nbttagcompound); + nbttagcompound1.put("Passengers", nbttaglist); + } + + protected CompoundTag b(CompoundTag nbttagcompound) { + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); + + nbttagcompound.remove("Riding"); + return nbttagcompound1; + } + } + + private static class DataConverterBook implements DataConverter { + + DataConverterBook() { + } + + public int getDataVersion() { + return 165; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:written_book".equals(cmp.getString("id"))) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (nbttagcompound1.contains("pages", 9)) { + ListTag nbttaglist = nbttagcompound1.getList("pages", 8); + + for (int i = 0; i < nbttaglist.size(); ++i) { + String s = nbttaglist.getString(i); + Component object = null; + + if (!"null".equals(s) && !StringUtil.isNullOrEmpty(s)) { + if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) { + object = Component.literal(s); + } else { + try { + object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); + if (object == null) { + object = Component.literal(""); + } + } catch (JsonParseException jsonparseexception) { + ; + } + + if (object == null) { + try { + object = Component.Serializer.fromJson(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; + } + } + + if (object == null) { + try { + object = Component.Serializer.fromJsonLenient(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; + } + } + + if (object == null) { + object = Component.literal(s); + } + } + } else { + object = Component.literal(""); + } + + nbttaglist.set(i, StringTag.valueOf(Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess()))); + } + + nbttagcompound1.put("pages", nbttaglist); + } + } + + return cmp; + } + } + + private static class DataConverterCookedFish implements DataConverter { + + private static final ResourceLocation a = ResourceLocation.parse("cooked_fished"); + + DataConverterCookedFish() { + } + + public int getDataVersion() { + return 502; + } + + public CompoundTag convert(CompoundTag cmp) { + if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(ResourceLocation.parse(cmp.getString("id")))) { + cmp.putString("id", "minecraft:cooked_fish"); + } + + return cmp; + } + } + + private static class DataConverterZombie implements DataConverter { + + private static final Random a = new Random(); + + DataConverterZombie() { + } + + public int getDataVersion() { + return 502; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("Zombie".equals(cmp.getString("id")) && cmp.getBoolean("IsVillager")) { + if (!cmp.contains("ZombieType", 99)) { + int i = -1; + + if (cmp.contains("VillagerProfession", 99)) { + try { + i = this.convert(cmp.getInt("VillagerProfession")); + } catch (RuntimeException runtimeexception) { + ; + } + } + + if (i == -1) { + i = this.convert(DataConverterZombie.a.nextInt(6)); + } + + cmp.putInt("ZombieType", i); + } + + cmp.remove("IsVillager"); + } + + return cmp; + } + + private int convert(int i) { + return i >= 0 && i < 6 ? i : -1; + } + } + + private static class DataConverterVBO implements DataConverter { + + DataConverterVBO() { + } + + public int getDataVersion() { + return 505; + } + + public CompoundTag convert(CompoundTag cmp) { + cmp.putString("useVbo", "true"); + return cmp; + } + } + + private static class DataConverterGuardian implements DataConverter { + + DataConverterGuardian() { + } + + public int getDataVersion() { + return 700; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("Guardian".equals(cmp.getString("id"))) { + if (cmp.getBoolean("Elder")) { + cmp.putString("id", "ElderGuardian"); + } + + cmp.remove("Elder"); + } + + return cmp; + } + } + + private static class DataConverterSkeleton implements DataConverter { + + DataConverterSkeleton() { + } + + public int getDataVersion() { + return 701; + } + + public CompoundTag convert(CompoundTag cmp) { + String s = cmp.getString("id"); + + if ("Skeleton".equals(s)) { + int i = cmp.getInt("SkeletonType"); + + if (i == 1) { + cmp.putString("id", "WitherSkeleton"); + } else if (i == 2) { + cmp.putString("id", "Stray"); + } + + cmp.remove("SkeletonType"); + } + + return cmp; + } + } + + private static class DataConverterZombieType implements DataConverter { + + DataConverterZombieType() { + } + + public int getDataVersion() { + return 702; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("Zombie".equals(cmp.getString("id"))) { + int i = cmp.getInt("ZombieType"); + + switch (i) { + case 0: + default: + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + cmp.putString("id", "ZombieVillager"); + cmp.putInt("Profession", i - 1); + break; + + case 6: + cmp.putString("id", "Husk"); + } + + cmp.remove("ZombieType"); + } + + return cmp; + } + } + + private static class DataConverterHorse implements DataConverter { + + DataConverterHorse() { + } + + public int getDataVersion() { + return 703; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("EntityHorse".equals(cmp.getString("id"))) { + int i = cmp.getInt("Type"); + + switch (i) { + case 0: + default: + cmp.putString("id", "Horse"); + break; + + case 1: + cmp.putString("id", "Donkey"); + break; + + case 2: + cmp.putString("id", "Mule"); + break; + + case 3: + cmp.putString("id", "ZombieHorse"); + break; + + case 4: + cmp.putString("id", "SkeletonHorse"); + } + + cmp.remove("Type"); + } + + return cmp; + } + } + + private static class DataConverterTileEntity implements DataConverter { + + private static final Map a = Maps.newHashMap(); + + DataConverterTileEntity() { + } + + public int getDataVersion() { + return 704; + } + + public CompoundTag convert(CompoundTag cmp) { + String s = DataConverterTileEntity.a.get(cmp.getString("id")); + + if (s != null) { + cmp.putString("id", s); + } + + return cmp; + } + + static { + DataConverterTileEntity.a.put("Airportal", "minecraft:end_portal"); + DataConverterTileEntity.a.put("Banner", "minecraft:banner"); + DataConverterTileEntity.a.put("Beacon", "minecraft:beacon"); + DataConverterTileEntity.a.put("Cauldron", "minecraft:brewing_stand"); + DataConverterTileEntity.a.put("Chest", "minecraft:chest"); + DataConverterTileEntity.a.put("Comparator", "minecraft:comparator"); + DataConverterTileEntity.a.put("Control", "minecraft:command_block"); + DataConverterTileEntity.a.put("DLDetector", "minecraft:daylight_detector"); + DataConverterTileEntity.a.put("Dropper", "minecraft:dropper"); + DataConverterTileEntity.a.put("EnchantTable", "minecraft:enchanting_table"); + DataConverterTileEntity.a.put("EndGateway", "minecraft:end_gateway"); + DataConverterTileEntity.a.put("EnderChest", "minecraft:ender_chest"); + DataConverterTileEntity.a.put("FlowerPot", "minecraft:flower_pot"); + DataConverterTileEntity.a.put("Furnace", "minecraft:furnace"); + DataConverterTileEntity.a.put("Hopper", "minecraft:hopper"); + DataConverterTileEntity.a.put("MobSpawner", "minecraft:mob_spawner"); + DataConverterTileEntity.a.put("Music", "minecraft:noteblock"); + DataConverterTileEntity.a.put("Piston", "minecraft:piston"); + DataConverterTileEntity.a.put("RecordPlayer", "minecraft:jukebox"); + DataConverterTileEntity.a.put("Sign", "minecraft:sign"); + DataConverterTileEntity.a.put("Skull", "minecraft:skull"); + DataConverterTileEntity.a.put("Structure", "minecraft:structure_block"); + DataConverterTileEntity.a.put("Trap", "minecraft:dispenser"); + } + } + + private static class DataConverterEntity implements DataConverter { + + private static final Map a = Maps.newHashMap(); + + DataConverterEntity() { + } + + public int getDataVersion() { + return 704; + } + + public CompoundTag convert(CompoundTag cmp) { + String s = DataConverterEntity.a.get(cmp.getString("id")); + + if (s != null) { + cmp.putString("id", s); + } + + return cmp; + } + + static { + DataConverterEntity.a.put("AreaEffectCloud", "minecraft:area_effect_cloud"); + DataConverterEntity.a.put("ArmorStand", "minecraft:armor_stand"); + DataConverterEntity.a.put("Arrow", "minecraft:arrow"); + DataConverterEntity.a.put("Bat", "minecraft:bat"); + DataConverterEntity.a.put("Blaze", "minecraft:blaze"); + DataConverterEntity.a.put("Boat", "minecraft:boat"); + DataConverterEntity.a.put("CaveSpider", "minecraft:cave_spider"); + DataConverterEntity.a.put("Chicken", "minecraft:chicken"); + DataConverterEntity.a.put("Cow", "minecraft:cow"); + DataConverterEntity.a.put("Creeper", "minecraft:creeper"); + DataConverterEntity.a.put("Donkey", "minecraft:donkey"); + DataConverterEntity.a.put("DragonFireball", "minecraft:dragon_fireball"); + DataConverterEntity.a.put("ElderGuardian", "minecraft:elder_guardian"); + DataConverterEntity.a.put("EnderCrystal", "minecraft:ender_crystal"); + DataConverterEntity.a.put("EnderDragon", "minecraft:ender_dragon"); + DataConverterEntity.a.put("Enderman", "minecraft:enderman"); + DataConverterEntity.a.put("Endermite", "minecraft:endermite"); + DataConverterEntity.a.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal"); + DataConverterEntity.a.put("FallingSand", "minecraft:falling_block"); + DataConverterEntity.a.put("Fireball", "minecraft:fireball"); + DataConverterEntity.a.put("FireworksRocketEntity", "minecraft:fireworks_rocket"); + DataConverterEntity.a.put("Ghast", "minecraft:ghast"); + DataConverterEntity.a.put("Giant", "minecraft:giant"); + DataConverterEntity.a.put("Guardian", "minecraft:guardian"); + DataConverterEntity.a.put("Horse", "minecraft:horse"); + DataConverterEntity.a.put("Husk", "minecraft:husk"); + DataConverterEntity.a.put("Item", "minecraft:item"); + DataConverterEntity.a.put("ItemFrame", "minecraft:item_frame"); + DataConverterEntity.a.put("LavaSlime", "minecraft:magma_cube"); + DataConverterEntity.a.put("LeashKnot", "minecraft:leash_knot"); + DataConverterEntity.a.put("MinecartChest", "minecraft:chest_minecart"); + DataConverterEntity.a.put("MinecartCommandBlock", "minecraft:commandblock_minecart"); + DataConverterEntity.a.put("MinecartFurnace", "minecraft:furnace_minecart"); + DataConverterEntity.a.put("MinecartHopper", "minecraft:hopper_minecart"); + DataConverterEntity.a.put("MinecartRideable", "minecraft:minecart"); + DataConverterEntity.a.put("MinecartSpawner", "minecraft:spawner_minecart"); + DataConverterEntity.a.put("MinecartTNT", "minecraft:tnt_minecart"); + DataConverterEntity.a.put("Mule", "minecraft:mule"); + DataConverterEntity.a.put("MushroomCow", "minecraft:mooshroom"); + DataConverterEntity.a.put("Ozelot", "minecraft:ocelot"); + DataConverterEntity.a.put("Painting", "minecraft:painting"); + DataConverterEntity.a.put("Pig", "minecraft:pig"); + DataConverterEntity.a.put("PigZombie", "minecraft:zombie_pigman"); + DataConverterEntity.a.put("PolarBear", "minecraft:polar_bear"); + DataConverterEntity.a.put("PrimedTnt", "minecraft:tnt"); + DataConverterEntity.a.put("Rabbit", "minecraft:rabbit"); + DataConverterEntity.a.put("Sheep", "minecraft:sheep"); + DataConverterEntity.a.put("Shulker", "minecraft:shulker"); + DataConverterEntity.a.put("ShulkerBullet", "minecraft:shulker_bullet"); + DataConverterEntity.a.put("Silverfish", "minecraft:silverfish"); + DataConverterEntity.a.put("Skeleton", "minecraft:skeleton"); + DataConverterEntity.a.put("SkeletonHorse", "minecraft:skeleton_horse"); + DataConverterEntity.a.put("Slime", "minecraft:slime"); + DataConverterEntity.a.put("SmallFireball", "minecraft:small_fireball"); + DataConverterEntity.a.put("SnowMan", "minecraft:snowman"); + DataConverterEntity.a.put("Snowball", "minecraft:snowball"); + DataConverterEntity.a.put("SpectralArrow", "minecraft:spectral_arrow"); + DataConverterEntity.a.put("Spider", "minecraft:spider"); + DataConverterEntity.a.put("Squid", "minecraft:squid"); + DataConverterEntity.a.put("Stray", "minecraft:stray"); + DataConverterEntity.a.put("ThrownEgg", "minecraft:egg"); + DataConverterEntity.a.put("ThrownEnderpearl", "minecraft:ender_pearl"); + DataConverterEntity.a.put("ThrownExpBottle", "minecraft:xp_bottle"); + DataConverterEntity.a.put("ThrownPotion", "minecraft:potion"); + DataConverterEntity.a.put("Villager", "minecraft:villager"); + DataConverterEntity.a.put("VillagerGolem", "minecraft:villager_golem"); + DataConverterEntity.a.put("Witch", "minecraft:witch"); + DataConverterEntity.a.put("WitherBoss", "minecraft:wither"); + DataConverterEntity.a.put("WitherSkeleton", "minecraft:wither_skeleton"); + DataConverterEntity.a.put("WitherSkull", "minecraft:wither_skull"); + DataConverterEntity.a.put("Wolf", "minecraft:wolf"); + DataConverterEntity.a.put("XPOrb", "minecraft:xp_orb"); + DataConverterEntity.a.put("Zombie", "minecraft:zombie"); + DataConverterEntity.a.put("ZombieHorse", "minecraft:zombie_horse"); + DataConverterEntity.a.put("ZombieVillager", "minecraft:zombie_villager"); + } + } + + private static class DataConverterPotionWater implements DataConverter { + + DataConverterPotionWater() { + } + + public int getDataVersion() { + return 806; + } + + public CompoundTag convert(CompoundTag cmp) { + String s = cmp.getString("id"); + + if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(s)) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (!nbttagcompound1.contains("Potion", 8)) { + nbttagcompound1.putString("Potion", "minecraft:water"); + } + + if (!cmp.contains("tag", 10)) { + cmp.put("tag", nbttagcompound1); + } + } + + return cmp; + } + } + + private static class DataConverterShulker implements DataConverter { + + DataConverterShulker() { + } + + public int getDataVersion() { + return 808; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:shulker".equals(cmp.getString("id")) && !cmp.contains("Color", 99)) { + cmp.putByte("Color", (byte) 10); + } + + return cmp; + } + } + + private static class DataConverterShulkerBoxItem implements DataConverter { + + public static final String[] a = new String[] { "minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box" }; + + DataConverterShulkerBoxItem() { + } + + public int getDataVersion() { + return 813; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:shulker_box".equals(cmp.getString("id")) && cmp.contains("tag", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("tag"); + + if (nbttagcompound1.contains("BlockEntityTag", 10)) { + CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + + if (nbttagcompound2.getList("Items", 10).isEmpty()) { + nbttagcompound2.remove("Items"); + } + + int i = nbttagcompound2.getInt("Color"); + + nbttagcompound2.remove("Color"); + if (nbttagcompound2.isEmpty()) { + nbttagcompound1.remove("BlockEntityTag"); + } + + if (nbttagcompound1.isEmpty()) { + cmp.remove("tag"); + } + + cmp.putString("id", DataConverterShulkerBoxItem.a[i % 16]); + } + } + + return cmp; + } + } + + private static class DataConverterShulkerBoxBlock implements DataConverter { + + DataConverterShulkerBoxBlock() { + } + + public int getDataVersion() { + return 813; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:shulker".equals(cmp.getString("id"))) { + cmp.remove("Color"); + } + + return cmp; + } + } + + private static class DataConverterLang implements DataConverter { + + DataConverterLang() { + } + + public int getDataVersion() { + return 816; + } + + public CompoundTag convert(CompoundTag cmp) { + if (cmp.contains("lang", 8)) { + cmp.putString("lang", cmp.getString("lang").toLowerCase(Locale.ROOT)); + } + + return cmp; + } + } + + private static class DataConverterTotem implements DataConverter { + + DataConverterTotem() { + } + + public int getDataVersion() { + return 820; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:totem".equals(cmp.getString("id"))) { + cmp.putString("id", "minecraft:totem_of_undying"); + } + + return cmp; + } + } + + private static class DataConverterBedBlock implements DataConverter { + + private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); + + DataConverterBedBlock() { + } + + public int getDataVersion() { + return 1125; + } + + public CompoundTag convert(CompoundTag cmp) { + try { + CompoundTag nbttagcompound1 = cmp.getCompound("Level"); + int i = nbttagcompound1.getInt("xPos"); + int j = nbttagcompound1.getInt("zPos"); + ListTag nbttaglist = nbttagcompound1.getList("TileEntities", 10); + ListTag nbttaglist1 = nbttagcompound1.getList("Sections", 10); + + for (int k = 0; k < nbttaglist1.size(); ++k) { + CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); + byte b0 = nbttagcompound2.getByte("Y"); + byte[] abyte = nbttagcompound2.getByteArray("Blocks"); + + for (int l = 0; l < abyte.length; ++l) { + if (416 == (abyte[l] & 255) << 4) { + int i1 = l & 15; + int j1 = l >> 8 & 15; + int k1 = l >> 4 & 15; + CompoundTag nbttagcompound3 = new CompoundTag(); + + nbttagcompound3.putString("id", "bed"); + nbttagcompound3.putInt("x", i1 + (i << 4)); + nbttagcompound3.putInt("y", j1 + (b0 << 4)); + nbttagcompound3.putInt("z", k1 + (j << 4)); + nbttaglist.add(nbttagcompound3); + } + } + } + } catch (Exception exception) { + DataConverterBedBlock.a.warn("Unable to datafix Bed blocks, level format may be missing tags."); + } + + return cmp; + } + } + + private static class DataConverterBedItem implements DataConverter { + + DataConverterBedItem() { + } + + public int getDataVersion() { + return 1125; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("minecraft:bed".equals(cmp.getString("id")) && cmp.getShort("Damage") == 0) { + cmp.putShort("Damage", (short) DyeColor.RED.getId()); + } + + return cmp; + } + } + + private static class DataConverterSignText implements DataConverter { + + public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { + MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + if (jsonelement.isJsonPrimitive()) { + return Component.literal(jsonelement.getAsString()); + } else if (jsonelement.isJsonArray()) { + JsonArray jsonarray = jsonelement.getAsJsonArray(); + MutableComponent ichatbasecomponent = null; + Iterator iterator = jsonarray.iterator(); + + while (iterator.hasNext()) { + JsonElement jsonelement1 = (JsonElement) iterator.next(); + MutableComponent ichatbasecomponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); + + if (ichatbasecomponent == null) { + ichatbasecomponent = ichatbasecomponent1; + } else { + ichatbasecomponent.append(ichatbasecomponent1); + } + } + + return ichatbasecomponent; + } else { + throw new JsonParseException("Don't know how to turn " + jsonelement + " into a Component"); + } + } + + public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + return this.a(jsonelement, type, jsondeserializationcontext); + } + }).create(); + + DataConverterSignText() { + } + + public int getDataVersion() { + return 101; + } + + public CompoundTag convert(CompoundTag cmp) { + if ("Sign".equals(cmp.getString("id"))) { + this.convert(cmp, "Text1"); + this.convert(cmp, "Text2"); + this.convert(cmp, "Text3"); + this.convert(cmp, "Text4"); + } + + return cmp; + } + + private void convert(CompoundTag nbttagcompound, String s) { + String s1 = nbttagcompound.getString(s); + Component object = null; + + if (!"null".equals(s1) && !StringUtil.isNullOrEmpty(s1)) { + if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) { + object = Component.literal(s1); + } else { + try { + object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); + if (object == null) { + object = Component.literal(""); + } + } catch (JsonParseException jsonparseexception) { + ; + } + + if (object == null) { + try { + object = Component.Serializer.fromJson(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; + } + } + + if (object == null) { + try { + object = Component.Serializer.fromJsonLenient(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; + } + } + + if (object == null) { + object = Component.literal(s1); + } + } + } else { + object = Component.literal(""); + } + + nbttagcompound.putString(s, Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess())); + } + } + + private static class DataInspectorPlayerVehicle implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (cmp.contains("RootVehicle", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); + + if (nbttagcompound1.contains("Entity", 10)) { + convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); + } + } + + return cmp; + } + } + + private static class DataInspectorLevelPlayer implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (cmp.contains("Player", 10)) { + convertCompound(LegacyType.PLAYER, cmp, "Player", sourceVer, targetVer); + } + + return cmp; + } + } + + private static class DataInspectorStructure implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + ListTag nbttaglist; + int j; + CompoundTag nbttagcompound1; + + if (cmp.contains("entities", 9)) { + nbttaglist = cmp.getList("entities", 10); + + for (j = 0; j < nbttaglist.size(); ++j) { + nbttagcompound1 = (CompoundTag) nbttaglist.get(j); + if (nbttagcompound1.contains("nbt", 10)) { + convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); + } + } + } + + if (cmp.contains("blocks", 9)) { + nbttaglist = cmp.getList("blocks", 10); + + for (j = 0; j < nbttaglist.size(); ++j) { + nbttagcompound1 = (CompoundTag) nbttaglist.get(j); + if (nbttagcompound1.contains("nbt", 10)) { + convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); + } + } + } + + return cmp; + } + } + + private static class DataInspectorChunks implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (cmp.contains("Level", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("Level"); + ListTag nbttaglist; + int j; + + if (nbttagcompound1.contains("Entities", 9)) { + nbttaglist = nbttagcompound1.getList("Entities", 10); + + for (j = 0; j < nbttaglist.size(); ++j) { + nbttaglist.set(j, convert(LegacyType.ENTITY, (CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); + } + } + + if (nbttagcompound1.contains("TileEntities", 9)) { + nbttaglist = nbttagcompound1.getList("TileEntities", 10); + + for (j = 0; j < nbttaglist.size(); ++j) { + nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); + } + } + } + + return cmp; + } + } + + private static class DataInspectorEntityPassengers implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (cmp.contains("Passengers", 9)) { + ListTag nbttaglist = cmp.getList("Passengers", 10); + + for (int j = 0; j < nbttaglist.size(); ++j) { + nbttaglist.set(j, convert(LegacyType.ENTITY, nbttaglist.getCompound(j), sourceVer, targetVer)); + } + } + + return cmp; + } + } + + private static class DataInspectorPlayer implements DataInspector { + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + convertItems(cmp, "Inventory", sourceVer, targetVer); + convertItems(cmp, "EnderItems", sourceVer, targetVer); + if (cmp.contains("ShoulderEntityLeft", 10)) { + convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityLeft", sourceVer, targetVer); + } + + if (cmp.contains("ShoulderEntityRight", 10)) { + convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityRight", sourceVer, targetVer); + } + + return cmp; + } + } + + private static class DataInspectorVillagers implements DataInspector { + ResourceLocation entityVillager = getKey("EntityVillager"); + + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (entityVillager.equals(ResourceLocation.parse(cmp.getString("id"))) && cmp.contains("Offers", 10)) { + CompoundTag nbttagcompound1 = cmp.getCompound("Offers"); + + if (nbttagcompound1.contains("Recipes", 9)) { + ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); + + for (int j = 0; j < nbttaglist.size(); ++j) { + CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); + + convertItem(nbttagcompound2, "buy", sourceVer, targetVer); + convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); + convertItem(nbttagcompound2, "sell", sourceVer, targetVer); + nbttaglist.set(j, nbttagcompound2); + } + } + } + + return cmp; + } + } + + private static class DataInspectorMobSpawnerMinecart implements DataInspector { + ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); + ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); + + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + String s = cmp.getString("id"); + if (entityMinecartMobSpawner.equals(ResourceLocation.parse(s))) { + cmp.putString("id", tileEntityMobSpawner.toString()); + convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); + cmp.putString("id", s); + } + + return cmp; + } + } + + private static class DataInspectorMobSpawnerMobs implements DataInspector { + ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); + + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (tileEntityMobSpawner.equals(ResourceLocation.parse(cmp.getString("id")))) { + if (cmp.contains("SpawnPotentials", 9)) { + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); + + for (int j = 0; j < nbttaglist.size(); ++j) { + CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); + + convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); + } + } + + convertCompound(LegacyType.ENTITY, cmp, "SpawnData", sourceVer, targetVer); + } + + return cmp; + } + } + + private static class DataInspectorCommandBlock implements DataInspector { + ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); + + @Override + public CompoundTag inspect(CompoundTag cmp, int sourceVer, int targetVer) { + if (tileEntityCommand.equals(ResourceLocation.parse(cmp.getString("id")))) { + cmp.putString("id", "Control"); + convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); + cmp.putString("id", "MinecartCommandBlock"); + } + + return cmp; + } + } +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightFakePlayer.java new file mode 100644 index 000000000..140daa63b --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightFakePlayer.java @@ -0,0 +1,87 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3; + +import com.mojang.authlib.GameProfile; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ClientInformation; +import net.minecraft.server.level.ParticleStatus; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.Stat; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraft.world.phys.Vec3; + +import java.util.OptionalInt; +import java.util.UUID; + +class PaperweightFakePlayer extends ServerPlayer { + private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); + private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false, ParticleStatus.ALL + ); + + PaperweightFakePlayer(ServerLevel world) { + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); + } + + @Override + public Vec3 position() { + return ORIGIN; + } + + @Override + public void tick() { + } + + @Override + public void die(DamageSource damagesource) { + } + + @Override + public OptionalInt openMenu(MenuProvider factory) { + return OptionalInt.empty(); + } + + @Override + public void updateOptions(ClientInformation clientOptions) { + } + + @Override + public void displayClientMessage(Component message, boolean actionBar) { + } + + @Override + public void awardStat(Stat stat, int amount) { + } + + @Override + public void awardStat(Stat stat) { + } + + @Override + public void openTextEdit(SignBlockEntity sign, boolean front) { + } +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightWorldNativeAccess.java new file mode 100644 index 000000000..86d3fb598 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/PaperweightWorldNativeAccess.java @@ -0,0 +1,192 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class PaperweightWorldNativeAccess implements WorldNativeAccess { + private static final int UPDATE = 1; + private static final int NOTIFY = 2; + + private final PaperweightAdapter adapter; + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference world) { + this.adapter = adapter; + this.world = world; + } + + private ServerLevel getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public LevelChunk getChunk(int x, int z) { + return getWorld().getChunk(x, z); + } + + @Override + public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.stateById(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); + } + + @Override + public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) { + return chunk.getBlockState(position); + } + + @Nullable + @Override + public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) { + return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); + } + + @Override + public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) { + return Block.updateFromNeighbourShapes(block, getWorld(), position); + } + + @Override + public BlockPos getPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPos position) { + getWorld().getChunkSource().getLightEngine().checkBlock(position); + } + + @Override + public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) { + // We will assume that the tile entity was created for us + BlockEntity tileEntity = getWorld().getBlockEntity(position); + if (tileEntity == null) { + return false; + } + Tag nativeTag = adapter.fromNativeLin(tag); + PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity); + return true; + } + + @Override + public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { + getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); + } + } + + @Override + public boolean isChunkTicking(LevelChunk chunk) { + return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); + } + + @Override + public void markBlockChanged(LevelChunk chunk, BlockPos position) { + if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { + getWorld().getChunkSource().blockChanged(position); + } + } + + @Override + public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + ServerLevel world = getWorld(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + world.updateNeighborsAt(pos, oldState.getBlock()); + } else { + // When we don't want events, manually run the physics without them. + Block block = oldState.getBlock(); + fireNeighborChanged(pos, world, block, pos.west()); + fireNeighborChanged(pos, world, block, pos.east()); + fireNeighborChanged(pos, world, block, pos.below()); + fireNeighborChanged(pos, world, block, pos.above()); + fireNeighborChanged(pos, world, block, pos.north()); + fireNeighborChanged(pos, world, block, pos.south()); + } + if (newState.hasAnalogOutputSignal()) { + world.updateNeighbourForOutputSignal(pos, newState.getBlock()); + } + } + + @Override + public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + ServerLevel world = getWorld(); + newState.onPlace(world, pos, oldState, false); + } + + private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { + world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, ExperimentalRedstoneUtils.initialOrientation(world, null, null), false); + } + + @Override + public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) { + ServerLevel world = getWorld(); + oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + CraftWorld craftWorld = world.getWorld(); + BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState)); + world.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit); + newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); + } + + @Override + public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + getWorld().onBlockStateChange(pos, oldState, newState); + } + + @Override + public void flush() { + + } +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/StaticRefraction.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/StaticRefraction.java new file mode 100644 index 000000000..c701df1d4 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_3/StaticRefraction.java @@ -0,0 +1,84 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3; + +import com.sk89q.worldedit.bukkit.adapter.Refraction; + +/** + * Dedicated class to map all names that we use. + * + *

+ * Overloads are split into multiple fields, as they CAN have different obfuscated names. + *

+ */ +public final class StaticRefraction { + public static final String GET_CHUNK_FUTURE_MAIN_THREAD = Refraction.pickName( + "getChunkFutureMainThread", "c" + ); + public static final String MAIN_THREAD_PROCESSOR = Refraction.pickName( + "mainThreadProcessor", "g" + ); + public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e"); + public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_"); + /** + * {@code addFreshEntityWithPassengers(Entity entity)}. + */ + public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY = Refraction.pickName( + "addFreshEntityWithPassengers", "a_" + ); + /** + * {@code addFreshEntityWithPassengers(Entity entity, CreatureSpawnEvent.SpawnReason reason)}. + */ + public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY_SPAWN_REASON = + Refraction.pickName("addFreshEntityWithPassengers", "a_"); + /** + * {@code addFreshEntity(Entity entity)}. + */ + public static final String ADD_FRESH_ENTITY = Refraction.pickName("addFreshEntity", "b"); + /** + * {@code getBlockEntity(BlockPos blockPos)}. + */ + public static final String GET_BLOCK_ENTITY = Refraction.pickName("getBlockEntity", "c_"); + /** + * {@code setBlock(BlockPos blockPos, BlockState blockState, int flags)}. + */ + public static final String SET_BLOCK = Refraction.pickName("setBlock", "a"); + /** + * {@code setBlock(BlockPos blockPos, BlockState blockState, int flags, int maxUpdateDepth)}. + */ + public static final String SET_BLOCK_MAX_UPDATE = Refraction.pickName("setBlock", "a"); + public static final String REMOVE_BLOCK = Refraction.pickName("removeBlock", "a"); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop)}. + */ + public static final String DESTROY_BLOCK = Refraction.pickName("destroyBlock", "b"); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity)}. + */ + public static final String DESTROY_BLOCK_BREAKING_ENTITY = Refraction.pickName( + "destroyBlock", "a" + ); + /** + * {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity, int maxUpdateDepth)}. + */ + public static final String DESTROY_BLOCK_BREAKING_ENTITY_MAX_UPDATE = Refraction.pickName( + "destroyBlock", "a" + ); +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightBlockMaterial.java new file mode 100644 index 000000000..f0358eb10 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightBlockMaterial.java @@ -0,0 +1,175 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.sk89q.worldedit.world.registry.BlockMaterial; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.EmptyBlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.PushReaction; +import org.bukkit.craftbukkit.block.data.CraftBlockData; + +import javax.annotation.Nullable; + +public class PaperweightBlockMaterial implements BlockMaterial { + + private final Block block; + private final BlockState blockState; + private final CraftBlockData craftBlockData; + private final org.bukkit.Material craftMaterial; + private final int opacity; + private final FaweCompoundTag tile; + + public PaperweightBlockMaterial(Block block) { + this(block, block.defaultBlockState()); + } + + public PaperweightBlockMaterial(Block block, BlockState blockState) { + this.block = block; + this.blockState = blockState; + this.craftBlockData = CraftBlockData.fromData(blockState); + this.craftMaterial = craftBlockData.getMaterial(); + opacity = blockState.getLightBlock(); + BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( + BlockPos.ZERO, + blockState + ); + tile = tileEntity == null + ? null + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); + } + + public Block getBlock() { + return block; + } + + public BlockState getState() { + return blockState; + } + + public CraftBlockData getCraftBlockData() { + return craftBlockData; + } + + @Override + public boolean isAir() { + return blockState.isAir(); + } + + @Override + public boolean isFullCube() { + return craftMaterial.isOccluding(); + } + + @Override + public boolean isOpaque() { + return blockState.canOcclude(); + } + + @Override + public boolean isPowerSource() { + return blockState.isSignalSource(); + } + + @Override + public boolean isLiquid() { + return !blockState.getFluidState().is(Fluids.EMPTY); + } + + @Override + public boolean isSolid() { + return blockState.isSolidRender(); + } + + @Override + public float getHardness() { + return craftBlockData.getState().destroySpeed; + } + + @Override + public float getResistance() { + return block.getExplosionResistance(); + } + + @Override + public float getSlipperiness() { + return block.getFriction(); + } + + @Override + public int getLightValue() { + return blockState.getLightEmission(); + } + + @Override + public int getLightOpacity() { + return opacity; + } + + @Override + public boolean isFragileWhenPushed() { + return blockState.getPistonPushReaction() == PushReaction.DESTROY; + } + + @Override + public boolean isUnpushable() { + return blockState.getPistonPushReaction() == PushReaction.BLOCK; + } + + @Override + public boolean isTicksRandomly() { + return blockState.isRandomlyTicking(); + } + + @SuppressWarnings("deprecation") + @Override + public boolean isMovementBlocker() { + return blockState.blocksMotion(); + } + + @Override + public boolean isBurnable() { + return craftMaterial.isBurnable(); + } + + @Override + public boolean isToolRequired() { + // Removed in 1.16.1, this is not present in higher versions + return false; + } + + @Override + public boolean isReplacedDuringPlacement() { + return blockState.canBeReplaced(); + } + + @Override + public boolean isTranslucent() { + return !blockState.canOcclude(); + } + + @Override + public boolean hasContainer() { + return block instanceof EntityBlock; + } + + @Override + public boolean isTile() { + return block instanceof EntityBlock; + } + + @Override + public @Nullable FaweCompoundTag defaultTile() { + return tile; + } + + @Override + public int getMapColor() { + // rgb field + return block.defaultMapColor().col; + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweAdapter.java new file mode 100644 index 000000000..40e6ead32 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweAdapter.java @@ -0,0 +1,619 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; +import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; +import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.entity.LazyBaseEntity; +import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; +import com.fastasyncworldedit.core.util.NbtUtils; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Codec; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_3.PaperweightAdapter; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3.regen.PaperweightRegen; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.registry.state.BooleanProperty; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; +import com.sk89q.worldedit.registry.state.IntegerProperty; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import com.sk89q.worldedit.world.entity.EntityType; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.registry.BlockMaterial; +import io.papermc.lib.PaperLib; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.WritableRegistry; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.chunk.LevelChunk; +import org.apache.logging.log4j.Logger; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.entity.Player; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static net.minecraft.core.registries.Registries.BIOME; + +public final class PaperweightFaweAdapter extends FaweAdapter { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + + static { + try { + CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave"); + } catch (NoSuchMethodException ignored) { // may not be present in newer paper versions + } + } + + private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil(); + + public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { + super(new PaperweightAdapter()); + } + + public Function blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); + } + + public static Property adaptProperty(net.minecraft.world.level.block.state.properties.Property property) { + return switch (property) { + case net.minecraft.world.level.block.state.properties.BooleanProperty booleanProperty -> + new BooleanProperty(booleanProperty.getName(), ImmutableList.copyOf(booleanProperty.getPossibleValues())); + case net.minecraft.world.level.block.state.properties.IntegerProperty integerProperty -> + new IntegerProperty(integerProperty.getName(), ImmutableList.copyOf(integerProperty.getPossibleValues())); + case net.minecraft.world.level.block.state.properties.EnumProperty enumProperty -> { + if (enumProperty.getValueClass() == net.minecraft.core.Direction.class) { + yield new DirectionalProperty(enumProperty.getName(), enumProperty.getPossibleValues().stream() + .map(StringRepresentable::getSerializedName) + .map(s -> s.toUpperCase(Locale.ROOT)) + .map(Direction::valueOf) + .toList() + ); + } + yield new EnumProperty(enumProperty.getName(), enumProperty.getPossibleValues().stream() + .map(StringRepresentable::getSerializedName).collect(Collectors.toCollection(ArrayList::new))); + } + default -> throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + property.getClass().getSimpleName()); + }; + } + + private static String getEntityId(Entity entity) { + return net.minecraft.world.entity.EntityType.getKey(entity.getType()).toString(); + } + + private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { + entity.save(compoundTag); + } + + @Override + public BukkitImplAdapter getParent() { + return parent; + } + + private synchronized boolean init() { + if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) { + return false; + } + ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size + ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size + for (int i = 0; i < ibdToStateOrdinal.length; i++) { + BlockState blockState = BlockTypesCache.states[i]; + PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial(); + int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState()); + char ordinal = blockState.getOrdinalChar(); + ibdToStateOrdinal[id] = ordinal; + ordinalToIbdID[ordinal] = id; + } + Map>> properties = new HashMap<>(); + try { + for (Field field : BlockStateProperties.class.getDeclaredFields()) { + Object obj = field.get(null); + if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property state)) { + continue; + } + Property property = adaptProperty(state); + properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> { + if (v == null) { + v = new ArrayList<>(Collections.singletonList(property)); + } else { + v.add(property); + } + return v; + }); + } + } catch (IllegalAccessException e) { + LOGGER.error("failed to initialize block states", e); + } finally { + allBlockProperties = ImmutableMap.copyOf(properties); + } + initialised = true; + return true; + } + + @Override + public BlockMaterial getMaterial(BlockType blockType) { + Block block = getBlock(blockType); + return new PaperweightBlockMaterial(block); + } + + @Override + public synchronized BlockMaterial getMaterial(BlockState state) { + net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); + return new PaperweightBlockMaterial(blockState.getBlock(), blockState); + } + + public Block getBlock(BlockType blockType) { + return DedicatedServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK) + .getValue(ResourceLocation.fromNamespaceAndPath(blockType.getNamespace(), blockType.getResource())); + } + + @Deprecated + @Override + public BlockState getBlock(Location location) { + Preconditions.checkNotNull(location); + + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + final ServerLevel handle = getServerLevel(location.getWorld()); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); + BlockState state = adapt(blockData); + if (state == null) { + org.bukkit.block.Block bukkitBlock = location.getBlock(); + state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); + } + return state; + } + + @Override + public BaseBlock getFullBlock(final Location location) { + Preconditions.checkNotNull(location); + + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + final ServerLevel handle = getServerLevel(location.getWorld()); + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + final BlockPos blockPos = new BlockPos(x, y, z); + final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); + BlockState state = adapt(blockData); + if (state == null) { + org.bukkit.block.Block bukkitBlock = location.getBlock(); + state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); + } + if (state.getBlockType().getMaterial().hasContainer()) { + + // Read the NBT data + BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); + if (blockEntity != null) { + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()); + return state.toBaseBlock((LinCompoundTag) toNativeLin(tag)); + } + } + + return state.toBaseBlock(); + } + + @Override + public Set getSupportedSideEffects() { + return SideEffectSet.defaults().getSideEffectsToApply(); + } + + @Override + public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { + return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); + } + + @Override + public BaseEntity getEntity(org.bukkit.entity.Entity entity) { + Preconditions.checkNotNull(entity); + + CraftEntity craftEntity = ((CraftEntity) entity); + Entity mcEntity = craftEntity.getHandle(); + + String id = getEntityId(mcEntity); + EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); + Supplier saveTag = () -> { + final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); + readEntityIntoTag(mcEntity, minecraftTag); + //add Id for AbstractChangeSet to work + final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag); + final Map> tags = NbtUtils.getLinCompoundTagValues(tag); + tags.put("Id", LinStringTag.of(id)); + return LinCompoundTag.of(tags); + }; + return new LazyBaseEntity(type, saveTag); + + } + + @Override + public Component getRichBlockName(BlockType blockType) { + return parent.getRichBlockName(blockType); + } + + @Override + public Component getRichItemName(ItemType itemType) { + return parent.getRichItemName(itemType); + } + + @Override + public Component getRichItemName(BaseItemStack itemStack) { + return parent.getRichItemName(itemStack); + } + + @Override + public OptionalInt getInternalBlockStateId(BlockState state) { + PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); + net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState(); + return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState)); + } + + @Override + public BlockState adapt(BlockData blockData) { + CraftBlockData cbd = ((CraftBlockData) blockData); + net.minecraft.world.level.block.state.BlockState ibd = cbd.getState(); + return adapt(ibd); + } + + public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + return BlockTypesCache.states[adaptToChar(blockState)]; + } + + public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) { + int id = Block.BLOCK_STATE_REGISTRY.getId(blockState); + if (initialised) { + return ibdToStateOrdinal[id]; + } + synchronized (this) { + if (initialised) { + return ibdToStateOrdinal[id]; + } + try { + init(); + return ibdToStateOrdinal[id]; + } catch (ArrayIndexOutOfBoundsException e1) { + LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!", + blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1 + ); + return BlockTypesCache.ReservedIDs.AIR; + } + } + } + + public char ibdIDToOrdinal(int id) { + if (initialised) { + return ibdToStateOrdinal[id]; + } + synchronized (this) { + if (initialised) { + return ibdToStateOrdinal[id]; + } + init(); + return ibdToStateOrdinal[id]; + } + } + + @Override + public char[] getIbdToStateOrdinal() { + if (initialised) { + return ibdToStateOrdinal; + } + synchronized (this) { + if (initialised) { + return ibdToStateOrdinal; + } + init(); + return ibdToStateOrdinal; + } + } + + public int ordinalToIbdID(char ordinal) { + if (initialised) { + return ordinalToIbdID[ordinal]; + } + synchronized (this) { + if (initialised) { + return ordinalToIbdID[ordinal]; + } + init(); + return ordinalToIbdID[ordinal]; + } + } + + @Override + public int[] getOrdinalToIbdID() { + if (initialised) { + return ordinalToIbdID; + } + synchronized (this) { + if (initialised) { + return ordinalToIbdID; + } + init(); + return ordinalToIbdID; + } + } + + @Override + public > BlockData adapt(B state) { + PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial(); + return material.getCraftBlockData(); + } + + @Override + public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { + ServerLevel nmsWorld = getServerLevel(world); + ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); + if (map != null && wasAccessibleSinceLastSave(map)) { + boolean flag = false; + // PlayerChunk.d players = map.players; + Stream stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) + */ Stream.empty(); + + ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle(); + stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer) + .forEach(entityPlayer -> { + synchronized (chunkPacket) { + ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket(); + if (nmsPacket == null) { + nmsPacket = mapUtil.create(this, chunkPacket); + chunkPacket.setNativePacket(nmsPacket); + } + try { + FaweCache.INSTANCE.CHUNK_FLAG.get().set(true); + entityPlayer.connection.send(nmsPacket); + } finally { + FaweCache.INSTANCE.CHUNK_FLAG.get().set(false); + } + } + }); + } + } + + @Override + public Map> getProperties(BlockType blockType) { + return getParent().getProperties(blockType); + } + + @Override + public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) { + int internalId = BlockStateIdAccess.getBlockStateId(blockState); + net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); + return blockState1.hasPostProcess( + getServerLevel(world), + new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z()) + ); + } + + @Override + public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); + ItemStack stack = new ItemStack( + registryAccess.lookupOrThrow(Registries.ITEM).getValueOrThrow(ResourceKey.create( + Registries.ITEM, ResourceLocation.parse(baseItemStack.getType().id()) + )), + baseItemStack.getAmount() + ); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNativeLin(baseItemStack.getNbt()); + if (nbt != null) { + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); + } + return CraftItemStack.asCraftMirror(stack); + } + + @Override + protected void preCaptureStates(final ServerLevel serverLevel) { + serverLevel.captureTreeGeneration = true; + serverLevel.captureBlockStates = true; + } + + @Override + protected List getCapturedBlockStatesCopy(final ServerLevel serverLevel) { + return new ArrayList<>(serverLevel.capturedBlockStates.values()); + } + + @Override + protected void postCaptureBlockStates(final ServerLevel serverLevel) { + serverLevel.captureBlockStates = false; + serverLevel.captureTreeGeneration = false; + serverLevel.capturedBlockStates.clear(); + } + + @Override + protected ServerLevel getServerLevel(final World world) { + return ((CraftWorld) world).getHandle(); + } + + @Override + public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); + final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), + itemStack.getAmount() + ); + } + + @Override + public Tag toNative(net.minecraft.nbt.Tag foreign) { + return parent.toNative(foreign); + } + + @Override + public net.minecraft.nbt.Tag fromNative(Tag foreign) { + return parent.fromNative(foreign); + } + + @Override + public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception { + return new PaperweightRegen(bukkitWorld, region, target, options).regenerate(); + } + + @Override + public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) { + return new PaperweightGetBlocks(world, chunkX, chunkZ); + } + + @Override + public int getInternalBiomeId(BiomeType biomeType) { + final Registry registry = MinecraftServer + .getServer() + .registryAccess() + .lookupOrThrow(BIOME); + ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id()); + Biome biome = registry.getValue(resourceLocation); + return registry.getId(biome); + } + + @Override + public Iterable getRegisteredBiomes() { + WritableRegistry biomeRegistry = (WritableRegistry) ((CraftServer) Bukkit.getServer()) + .getServer() + .registryAccess() + .lookupOrThrow(BIOME); + List keys = biomeRegistry.stream() + .map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); + List namespacedKeys = new ArrayList<>(); + for (ResourceLocation key : keys) { + try { + namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key)); + } catch (IllegalArgumentException e) { + LOGGER.error("Error converting biome key {}", key.toString(), e); + } + } + return namespacedKeys; + } + + @Override + public RelighterFactory getRelighterFactory() { + if (PaperLib.isPaper()) { + return new PaperweightStarlightRelighterFactory(); + } else { + return new NMSRelighterFactory(); + } + } + + @Override + public Map>> getAllProperties() { + if (initialised) { + return allBlockProperties; + } + synchronized (this) { + if (initialised) { + return allBlockProperties; + } + init(); + return allBlockProperties; + } + } + + @Override + public IBatchProcessor getTickingPostProcessor() { + return new PaperweightPostProcessor(); + } + + private boolean wasAccessibleSinceLastSave(ChunkHolder holder) { + if (PaperLib.isPaper()) { // Papers new chunk system has no related replacement - therefor we assume true. + return true; + } + try { + return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder); + } catch (IllegalAccessException | InvocationTargetException ignored) { + return false; + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweWorldNativeAccess.java new file mode 100644 index 000000000..ab2e0a277 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightFaweWorldNativeAccess.java @@ -0,0 +1,294 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.task.RunnableVal; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.enginehub.linbus.tree.LinCompoundTag; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess { + + private static final int UPDATE = 1; + private static final int NOTIFY = 2; + private static final Direction[] NEIGHBOUR_ORDER = { + Direction.EAST, + Direction.WEST, + Direction.DOWN, + Direction.UP, + Direction.NORTH, + Direction.SOUTH + }; + private final PaperweightFaweAdapter paperweightFaweAdapter; + private final WeakReference level; + private final AtomicInteger lastTick; + private final Set cachedChanges = new HashSet<>(); + private final Set cachedChunksToSend = new HashSet<>(); + private SideEffectSet sideEffectSet; + + public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { + this.paperweightFaweAdapter = paperweightFaweAdapter; + this.level = level; + // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. + // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. + this.lastTick = new AtomicInteger(MinecraftServer.currentTick); + } + + private Level getLevel() { + return Objects.requireNonNull(level.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public LevelChunk getChunk(int x, int z) { + return getLevel().getChunk(x, z); + } + + @Override + public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) { + int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar()); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.stateById(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState(); + } + + @Override + public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) { + return levelChunk.getBlockState(blockPos); + } + + @Nullable + @Override + public synchronized net.minecraft.world.level.block.state.BlockState setBlockState( + LevelChunk levelChunk, BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState blockState + ) { + int currentTick = MinecraftServer.currentTick; + if (Fawe.isMainThread()) { + return levelChunk.setBlockState(blockPos, blockState, + this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) + ); + } + // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) + cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); + cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ)); + boolean nextTick = lastTick.get() > currentTick; + if (nextTick || cachedChanges.size() >= 1024) { + if (nextTick) { + lastTick.set(currentTick); + } + flushAsync(nextTick); + } + return blockState; + } + + @Override + public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( + net.minecraft.world.level.block.state.BlockState blockState, + BlockPos blockPos + ) { + return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos); + } + + @Override + public BlockPos getPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPos blockPos) { + getLevel().getChunkSource().getLightEngine().checkBlock(blockPos); + } + + @Override + public boolean updateTileEntity(BlockPos blockPos, LinCompoundTag tag) { + // We will assume that the tile entity was created for us, + // though we do not do this on the other versions + BlockEntity blockEntity = getLevel().getBlockEntity(blockPos); + if (blockEntity == null) { + return false; + } + net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeLin(tag); + blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess()); + return true; + } + + @Override + public void notifyBlockUpdate( + LevelChunk levelChunk, BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState oldState, + net.minecraft.world.level.block.state.BlockState newState + ) { + if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { + getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY); + } + } + + @Override + public boolean isChunkTicking(LevelChunk levelChunk) { + return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); + } + + @Override + public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) { + if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) { + ((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos); + } + } + + @Override + public void notifyNeighbors( + BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState oldState, + net.minecraft.world.level.block.state.BlockState newState + ) { + Level level = getLevel(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + level.blockUpdated(blockPos, oldState.getBlock()); + } else { + // When we don't want events, manually run the physics without them. + // Un-nest neighbour updating + for (Direction direction : NEIGHBOUR_ORDER) { + BlockPos shifted = blockPos.relative(direction); + level.getBlockState(shifted).handleNeighborChanged(level, shifted, oldState.getBlock(), ExperimentalRedstoneUtils.initialOrientation(level, null, null), false); + } + } + if (newState.hasAnalogOutputSignal()) { + level.updateNeighbourForOutputSignal(blockPos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors( + BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState oldState, + net.minecraft.world.level.block.state.BlockState newState, + int recursionLimit + ) { + Level level = getLevel(); + // a == updateNeighbors + // b == updateDiagonalNeighbors + oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + CraftWorld craftWorld = level.getWorld(); + if (craftWorld != null) { + BlockPhysicsEvent event = new BlockPhysicsEvent( + craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), + CraftBlockData.fromData(newState) + ); + level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + } + newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit); + newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit); + } + + @Override + public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { + Level world = getLevel(); + newState.onPlace(world, pos, oldState, false); + } + + @Override + public void onBlockStateChange( + BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState oldState, + net.minecraft.world.level.block.state.BlockState newState + ) { + getLevel().onBlockStateChange(blockPos, oldState, newState); + } + + private synchronized void flushAsync(final boolean sendChunks) { + final Set changes = Set.copyOf(cachedChanges); + cachedChanges.clear(); + final Set toSend; + if (sendChunks) { + toSend = Set.copyOf(cachedChunksToSend); + cachedChunksToSend.clear(); + } else { + toSend = Collections.emptySet(); + } + RunnableVal runnableVal = new RunnableVal<>() { + @Override + public void run(Object value) { + changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, + sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) + )); + if (!sendChunks) { + return; + } + for (IntPair chunk : toSend) { + PaperweightPlatformAdapter.sendChunk(chunk, getLevel().getWorld().getHandle(), chunk.x(), chunk.z()); + } + } + }; + TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + } + + @Override + public synchronized void flush() { + RunnableVal runnableVal = new RunnableVal<>() { + @Override + public void run(Object value) { + cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, + sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) + )); + for (IntPair chunk : cachedChunksToSend) { + PaperweightPlatformAdapter.sendChunk(chunk, getLevel().getWorld().getHandle(), chunk.x(), chunk.z()); + } + } + }; + if (Fawe.isMainThread()) { + runnableVal.run(); + } else { + TaskManager.taskManager().sync(runnableVal); + } + cachedChanges.clear(); + cachedChunksToSend.clear(); + } + + private record CachedChange( + LevelChunk levelChunk, + BlockPos blockPos, + net.minecraft.world.level.block.state.BlockState blockState + ) { + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks.java new file mode 100644 index 000000000..1d04075f3 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks.java @@ -0,0 +1,1199 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks; +import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.QueueHandler; +import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.NbtUtils; +import com.fastasyncworldedit.core.util.collection.AdaptedMap; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.internal.Constants; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; +import io.papermc.paper.event.block.BeaconDeactivatedEvent; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.IdMap; +import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.BitStorage; +import net.minecraft.util.ZeroBitStorage; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.entity.BeaconBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.DataLayer; +import net.minecraft.world.level.chunk.HashMapPalette; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.LinearPalette; +import net.minecraft.world.level.chunk.Palette; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.PalettedContainerRO; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.lighting.LevelLightEngine; +import org.apache.logging.log4j.Logger; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.CraftBlock; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Function; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); + private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()); + private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); + private final ServerLevel serverLevel; + private final int chunkX; + private final int chunkZ; + private final IntPair chunkPos; + private final int minHeight; + private final int maxHeight; + private final int minSectionPosition; + private final int maxSectionPosition; + private final Registry biomeRegistry; + private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); + private LevelChunkSection[] sections; + private LevelChunk levelChunk; + private DataLayer[] blockLight; + private DataLayer[] skyLight; + private boolean createCopy = false; + private boolean forceLoadSections = true; + private boolean lightUpdate = false; + private int copyKey = 0; + + public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { + this(((CraftWorld) world).getHandle(), chunkX, chunkZ); + } + + public PaperweightGetBlocks(ServerLevel serverLevel, int chunkX, int chunkZ) { + super(serverLevel.getMinY() >> 4, (serverLevel.getMaxY() - 1) >> 4); + this.serverLevel = serverLevel; + this.chunkX = chunkX; + this.chunkZ = chunkZ; + this.minHeight = serverLevel.getMinY(); + this.maxHeight = serverLevel.getMaxY() - 1; // Minecraft max limit is exclusive. + this.minSectionPosition = minHeight >> 4; + this.maxSectionPosition = maxHeight >> 4; + this.skyLight = new DataLayer[getSectionCount()]; + this.blockLight = new DataLayer[getSectionCount()]; + this.biomeRegistry = serverLevel.registryAccess().lookupOrThrow(BIOME); + this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); + } + + public int getChunkX() { + return chunkX; + } + + public int getChunkZ() { + return chunkZ; + } + + @Override + public boolean isCreateCopy() { + return createCopy; + } + + @Override + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } + this.createCopy = createCopy; + // Increment regardless of whether copy will be created or not to return null from getCopy() + return ++this.copyKey; + } + + @Override + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); + } + + @Override + public void setLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { + if (light != null) { + lightUpdate = true; + try { + fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + @Override + public void setSkyLightingToGet(char[][] light, int minSectionPosition, int maxSectionPosition) { + if (light != null) { + lightUpdate = true; + try { + fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + @Override + public void setHeightmapToGet(HeightMapType type, int[] data) { + // height + 1 to match server internal + BitArrayUnstretched bitArray = new BitArrayUnstretched(MathMan.log2nlz(getChunk().getHeight() + 1), 256); + bitArray.fromRaw(data); + Heightmap.Types nativeType = Heightmap.Types.valueOf(type.name()); + Heightmap heightMap = getChunk().heightmaps.get(nativeType); + heightMap.setRawData(getChunk(), nativeType, bitArray.getData()); + } + + @Override + public int getMaxY() { + return maxHeight; + } + + @Override + public int getMinY() { + return minHeight; + } + + @Override + public BiomeType getBiomeType(int x, int y, int z) { + LevelChunkSection section = getSections(false)[(y >> 4) - getMinSectionPosition()]; + Holder biomes = section.getNoiseBiome(x >> 2, (y & 15) >> 2, z >> 2); + return PaperweightPlatformAdapter.adapt(biomes, serverLevel); + } + + @Override + public void removeSectionLighting(int layer, boolean sky) { + SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); + DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.BLOCK).getDataLayerData( + sectionPos); + if (dataLayer != null) { + lightUpdate = true; + synchronized (dataLayer) { + byte[] bytes = dataLayer.getData(); + Arrays.fill(bytes, (byte) 0); + } + } + if (sky) { + SectionPos sectionPos1 = SectionPos.of(getChunk().getPos(), layer); + DataLayer dataLayer1 = serverLevel + .getChunkSource() + .getLightEngine() + .getLayerListener(LightLayer.SKY) + .getDataLayerData(sectionPos1); + if (dataLayer1 != null) { + lightUpdate = true; + synchronized (dataLayer1) { + byte[] bytes = dataLayer1.getData(); + Arrays.fill(bytes, (byte) 0); + } + } + } + } + + @Override + public FaweCompoundTag tile(final int x, final int y, final int z) { + BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( + chunkX << 4), y, (z & 15) + ( + chunkZ << 4))); + if (blockEntity == null) { + return null; + } + return NMS_TO_TILE.apply(blockEntity); + + } + + @Override + public Map tiles() { + Map nmsTiles = getChunk().getBlockEntities(); + if (nmsTiles.isEmpty()) { + return Collections.emptyMap(); + } + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); + } + + @Override + public int getSkyLight(int x, int y, int z) { + int layer = y >> 4; + int alayer = layer - getMinSectionPosition(); + if (skyLight[alayer] == null) { + SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); + DataLayer dataLayer = + serverLevel.getChunkSource().getLightEngine().getLayerListener(LightLayer.SKY).getDataLayerData(sectionPos); + // If the server hasn't generated the section's NibbleArray yet, it will be null + if (dataLayer == null) { + byte[] LAYER_COUNT = new byte[2048]; + // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. + Arrays.fill(LAYER_COUNT, (byte) 15); + dataLayer = new DataLayer(LAYER_COUNT); + ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( + LightLayer.BLOCK, + sectionPos, + dataLayer + ); + } + skyLight[alayer] = dataLayer; + } + return skyLight[alayer].get(x & 15, y & 15, z & 15); + } + + @Override + public int getEmittedLight(int x, int y, int z) { + int layer = y >> 4; + int alayer = layer - getMinSectionPosition(); + if (blockLight[alayer] == null) { + serverLevel.getRawBrightness(new BlockPos(1, 1, 1), 5); + SectionPos sectionPos = SectionPos.of(getChunk().getPos(), layer); + DataLayer dataLayer = serverLevel + .getChunkSource() + .getLightEngine() + .getLayerListener(LightLayer.BLOCK) + .getDataLayerData(sectionPos); + // If the server hasn't generated the section's DataLayer yet, it will be null + if (dataLayer == null) { + byte[] LAYER_COUNT = new byte[2048]; + // Safe enough to assume if it's not created, it's under the sky. Unlikely to be created before lighting is fixed anyway. + Arrays.fill(LAYER_COUNT, (byte) 15); + dataLayer = new DataLayer(LAYER_COUNT); + ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, + dataLayer + ); + } + blockLight[alayer] = dataLayer; + } + return blockLight[alayer].get(x & 15, y & 15, z & 15); + } + + @Override + public int[] getHeightMap(HeightMapType type) { + long[] longArray = getChunk().heightmaps.get(Heightmap.Types.valueOf(type.name())).getRawData(); + BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256, longArray); + return bitArray.toRaw(new int[256]); + } + + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } + if (entity != null) { + org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); + } + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { + return tag; + } + } + return null; + } + + @Override + public Collection entities() { + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + if (entities.isEmpty()) { + return Collections.emptyList(); + } + int size = entities.size(); + return new AbstractCollection<>() { + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object get) { + if (!(get instanceof FaweCompoundTag getTag)) { + return false; + } + UUID getUUID = NbtUtils.uuid(getTag); + for (Entity entity : entities) { + UUID uuid = entity.getUUID(); + if (uuid.equals(getUUID)) { + return true; + } + } + return false; + } + + @Nonnull + @Override + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { + CompoundTag tag = new CompoundTag(); + input.save(tag); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; + return result.iterator(); + } + }; + + } + + private void removeEntity(Entity entity) { + entity.discard(); + } + + public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) { + return PaperweightPlatformAdapter.ensureLoaded(nmsWorld, chunkX, chunkZ); + } + + @Override + @SuppressWarnings("rawtypes") + public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } + forceLoadSections = false; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } + try { + // Remove existing tiles. Create a copy so that we can remove blocks + Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); + List beacons = null; + if (!chunkTiles.isEmpty()) { + for (Map.Entry entry : chunkTiles.entrySet()) { + final BlockPos pos = entry.getKey(); + final int lx = pos.getX() & 15; + final int ly = pos.getY(); + final int lz = pos.getZ() & 15; + final int layer = ly >> 4; + if (!set.hasSection(layer)) { + continue; + } + + int ordinal = set.getBlock(lx, ly, lz).getOrdinal(); + if (ordinal != BlockTypesCache.ReservedIDs.__RESERVED__) { + BlockEntity tile = entry.getValue(); + if (PaperLib.isPaper() && tile instanceof BeaconBlockEntity) { + if (beacons == null) { + beacons = new ArrayList<>(); + } + beacons.add(tile); + PaperweightPlatformAdapter.removeBeacon(tile, nmsChunk); + continue; + } + nmsChunk.removeBlockEntity(tile.getBlockPos()); + if (createCopy) { + copy.storeTile(tile); + } + } + } + } + final BiomeType[][] biomes = set.getBiomes(); + + int bitMask = 0; + synchronized (nmsChunk) { + LevelChunkSection[] levelChunkSections = nmsChunk.getSections(); + + for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) { + + int getSectionIndex = layerNo - getMinSectionPosition(); + int setSectionIndex = layerNo - set.getMinSectionPosition(); + + if (!set.hasSection(layerNo)) { + // No blocks, but might be biomes present. Handle this lazily. + if (biomes == null) { + continue; + } + if (layerNo < set.getMinSectionPosition() || layerNo > set.getMaxSectionPosition()) { + continue; + } + if (biomes[setSectionIndex] != null) { + synchronized (super.sectionLocks[getSectionIndex]) { + LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; + if (createCopy && existingSection != null) { + copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); + } + + if (existingSection == null) { + PalettedContainer> biomeData = PaperweightPlatformAdapter.getBiomePalettedContainer( + biomes[setSectionIndex], + biomeHolderIdMap + ); + LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + new char[4096], + adapter, + biomeRegistry, + biomeData + ); + if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, + levelChunkSections, + null, + newSection, + getSectionIndex + )) { + updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); + continue; + } else { + existingSection = levelChunkSections[getSectionIndex]; + if (existingSection == null) { + LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, + getSectionIndex + ); + continue; + } + } + } else { + PalettedContainer> paletteBiomes = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + if (paletteBiomes != null) { + PaperweightPlatformAdapter.setBiomesToChunkSection(existingSection, paletteBiomes); + } + } + } + } + continue; + } + + bitMask |= 1 << getSectionIndex; + + // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to + // this chunk GET when #updateGet is called. Future dords, please listen this time. + char[] tmp = set.load(layerNo); + char[] setArr = new char[tmp.length]; + System.arraycopy(tmp, 0, setArr, 0, tmp.length); + + // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was + // submitted to keep loaded internal chunks to queue target size. + synchronized (super.sectionLocks[getSectionIndex]) { + + LevelChunkSection newSection; + LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; + // Don't attempt to tick section whilst we're editing + if (existingSection != null) { + PaperweightPlatformAdapter.clearCounts(existingSection); + } + + if (createCopy) { + char[] tmpLoad = loadPrivately(layerNo); + char[] copyArr = new char[4096]; + System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); + copy.storeSection(getSectionIndex, copyArr); + if (biomes != null && existingSection != null) { + copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); + } + } + + if (existingSection == null) { + PalettedContainer> biomeData = biomes == null ? new PalettedContainer<>( + biomeHolderIdMap, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES + ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + setArr, + adapter, + biomeRegistry, + biomeData + ); + if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, + levelChunkSections, + null, + newSection, + getSectionIndex + )) { + updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex); + continue; + } else { + existingSection = levelChunkSections[getSectionIndex]; + if (existingSection == null) { + LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, + getSectionIndex + ); + continue; + } + } + } + + //ensure that the server doesn't try to tick the chunksection while we're editing it. (Again) + PaperweightPlatformAdapter.clearCounts(existingSection); + DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection); + + // Synchronize to prevent further acquisitions + synchronized (lock) { + lock.acquire(); // Wait until we have the lock + lock.release(); + try { + sectionLock.writeLock().lock(); + if (this.getChunk() != nmsChunk) { + this.levelChunk = nmsChunk; + this.sections = null; + this.reset(); + } else if (existingSection != getSections(false)[getSectionIndex]) { + this.sections[getSectionIndex] = existingSection; + this.reset(); + } else if (!Arrays.equals( + update(getSectionIndex, new char[4096], true), + loadPrivately(layerNo) + )) { + this.reset(layerNo); + /*} else if (lock.isModified()) { + this.reset(layerNo);*/ + } + } finally { + sectionLock.writeLock().unlock(); + } + + PalettedContainer> biomeData = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); + + newSection = PaperweightPlatformAdapter.newChunkSection( + layerNo, + this::loadPrivately, + setArr, + adapter, + biomeRegistry, + biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() + ); + if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, + levelChunkSections, + existingSection, + newSection, + getSectionIndex + )) { + LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, + getSectionIndex + ); + } else { + updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex); + } + } + } + } + + Map heightMaps = set.getHeightMaps(); + for (Map.Entry entry : heightMaps.entrySet()) { + PaperweightGetBlocks.this.setHeightmapToGet(entry.getKey(), entry.getValue()); + } + PaperweightGetBlocks.this.setLightingToGet( + set.getLight(), + set.getMinSectionPosition(), + set.getMaxSectionPosition() + ); + PaperweightGetBlocks.this.setSkyLightingToGet( + set.getSkyLight(), + set.getMinSectionPosition(), + set.getMaxSectionPosition() + ); + + Runnable[] syncTasks = null; + + int bx = chunkX << 4; + int bz = chunkZ << 4; + + // Call beacon deactivate events here synchronously + // list will be null on spigot, so this is an implicit isPaper check + if (beacons != null && !beacons.isEmpty()) { + final List finalBeacons = beacons; + + syncTasks = new Runnable[4]; + + syncTasks[3] = () -> { + for (BlockEntity beacon : finalBeacons) { + BeaconBlockEntity.playSound(beacon.getLevel(), beacon.getBlockPos(), SoundEvents.BEACON_DEACTIVATE); + new BeaconDeactivatedEvent(CraftBlock.at(beacon.getLevel(), beacon.getBlockPos())).callEvent(); + } + }; + } + + Set entityRemoves = set.getEntityRemoves(); + if (entityRemoves != null && !entityRemoves.isEmpty()) { + if (syncTasks == null) { + syncTasks = new Runnable[3]; + } + + syncTasks[2] = () -> { + Set entitiesRemoved = new HashSet<>(); + final List entities = PaperweightPlatformAdapter.getEntities(nmsChunk); + + for (Entity entity : entities) { + UUID uuid = entity.getUUID(); + if (entityRemoves.contains(uuid)) { + if (createCopy) { + copy.storeEntity(entity); + } + removeEntity(entity); + entitiesRemoved.add(uuid); + entityRemoves.remove(uuid); + } + } + if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { + for (UUID uuid : entityRemoves) { + Entity entity = serverLevel.getEntities().get(uuid); + if (entity != null) { + removeEntity(entity); + } + } + } + // Only save entities that were actually removed to history + set.getEntityRemoves().clear(); + set.getEntityRemoves().addAll(entitiesRemoved); + }; + } + + Collection entities = set.entities(); + if (entities != null && !entities.isEmpty()) { + if (syncTasks == null) { + syncTasks = new Runnable[2]; + } + + syncTasks[1] = () -> { + Iterator iterator = entities.iterator(); + while (iterator.hasNext()) { + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); + if (idTag == null || posTag == null || rotTag == null) { + LOGGER.error("Unknown entity tag: {}", nativeTag); + continue; + } + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); + + EntityType type = EntityType.byString(id).orElse(null); + if (type != null) { + Entity entity = type.create(serverLevel, EntitySpawnReason.COMMAND); + if (entity != null) { + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); + for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.load(tag); + entity.absMoveTo(x, y, z, yaw, pitch); + entity.setUUID(NbtUtils.uuid(nativeTag)); + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + LOGGER.warn( + "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", + id, + serverLevel.getWorld().getName(), + x, + y, + z + ); + // Unsuccessful create should not be saved to history + iterator.remove(); + } + } + } + } + }; + } + + // set tiles + Map tiles = set.tiles(); + if (tiles != null && !tiles.isEmpty()) { + if (syncTasks == null) { + syncTasks = new Runnable[1]; + } + + syncTasks[0] = () -> { + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); + final BlockVector3 blockHash = entry.getKey(); + final int x = blockHash.x() + bx; + final int y = blockHash.y(); + final int z = blockHash.z() + bz; + final BlockPos pos = new BlockPos(x, y, z); + + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); + if (tileEntity == null || tileEntity.isRemoved()) { + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); + } + if (tileEntity != null) { + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); + tag.put("x", IntTag.valueOf(x)); + tag.put("y", IntTag.valueOf(y)); + tag.put("z", IntTag.valueOf(z)); + tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess()); + } + } + } + }; + } + + Runnable callback; + if (bitMask == 0 && biomes == null && !lightUpdate) { + callback = null; + } else { + int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; + callback = () -> { + // Set Modified + nmsChunk.setLightCorrect(true); // Set Modified + nmsChunk.mustNotSave = false; + nmsChunk.markUnsaved(); + // send to player + if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) { + this.send(); + } + if (finalizer != null) { + finalizer.run(); + } + }; + } + if (syncTasks != null) { + QueueHandler queueHandler = Fawe.instance().getQueueHandler(); + Runnable[] finalSyncTasks = syncTasks; + + // Chain the sync tasks and the callback + Callable chain = () -> { + try { + // Run the sync tasks + for (Runnable task : finalSyncTasks) { + if (task != null) { + task.run(); + } + } + if (callback == null) { + if (finalizer != null) { + queueHandler.async(finalizer, null); + } + return null; + } else { + return queueHandler.async(callback, null); + } + } catch (Throwable e) { + e.printStackTrace(); + throw e; + } + }; + //noinspection unchecked - required at compile time + return (T) (Future) queueHandler.sync(chain); + } else { + if (callback == null) { + if (finalizer != null) { + finalizer.run(); + } + } else { + callback.run(); + } + } + } + return null; + } catch (Throwable e) { + e.printStackTrace(); + return null; + } finally { + forceLoadSections = true; + } + } + + private void updateGet( + LevelChunk nmsChunk, + LevelChunkSection[] chunkSections, + LevelChunkSection section, + char[] arr, + int layer + ) { + try { + sectionLock.writeLock().lock(); + if (this.getChunk() != nmsChunk) { + this.levelChunk = nmsChunk; + this.sections = new LevelChunkSection[chunkSections.length]; + System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); + this.reset(); + } + if (this.sections == null) { + this.sections = new LevelChunkSection[chunkSections.length]; + System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length); + } + if (this.sections[layer] != section) { + // Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords + this.sections[layer] = new LevelChunkSection[]{section}.clone()[0]; + } + } finally { + sectionLock.writeLock().unlock(); + } + this.blocks[layer] = arr; + } + + private char[] loadPrivately(int layer) { + layer -= getMinSectionPosition(); + if (super.sections[layer] != null) { + synchronized (super.sectionLocks[layer]) { + if (super.sections[layer].isFull() && super.blocks[layer] != null) { + return super.blocks[layer]; + } + } + } + return PaperweightGetBlocks.this.update(layer, null, true); + } + + @Override + public void send() { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); + } + } + + /** + * Update a given (nullable) data array to the current data stored in the server's chunk, associated with this + * {@link PaperweightPlatformAdapter} instance. Not synchronised to the {@link PaperweightPlatformAdapter} instance as synchronisation + * is handled where necessary in the method, and should otherwise be handled correctly by this method's caller. + * + * @param layer layer index (0 may denote a negative layer in the world, e.g. at y=-32) + * @param data array to be updated/filled with data or null + * @param aggressive if the cached section array should be re-acquired. + * @return the given array to be filled with data, or a new array if null is given. + */ + @Override + @SuppressWarnings("unchecked") + public char[] update(int layer, char[] data, boolean aggressive) { + LevelChunkSection section = getSections(aggressive)[layer]; + // Section is null, return empty array + if (section == null) { + data = new char[4096]; + Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + return data; + } + if (data != null && data.length != 4096) { + data = new char[4096]; + Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + } + if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { + data = new char[4096]; + Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + } + Semaphore lock = PaperweightPlatformAdapter.applyLock(section); + synchronized (lock) { + // Efficiently convert ChunkSection to raw data + try { + lock.acquire(); + + final PalettedContainer blocks = section.getStates(); + final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocks); + final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); + + if (bits instanceof ZeroBitStorage) { + Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper + return data; + } + + final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get(dataObject); + + final int bitsPerEntry = bits.getBits(); + final long[] blockStates = bits.getRaw(); + + new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data); + + int num_palette; + if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { + num_palette = palette.getSize(); + } else { + // The section's palette is the global block palette. + for (int i = 0; i < 4096; i++) { + char paletteVal = data[i]; + char ordinal = adapter.ibdIDToOrdinal(paletteVal); + data[i] = ordinal; + } + return data; + } + + char[] paletteToOrdinal = FaweCache.INSTANCE.PALETTE_TO_BLOCK_CHAR.get(); + try { + if (num_palette != 1) { + for (int i = 0; i < num_palette; i++) { + char ordinal = ordinal(palette.valueFor(i), adapter); + paletteToOrdinal[i] = ordinal; + } + for (int i = 0; i < 4096; i++) { + char paletteVal = data[i]; + char val = paletteToOrdinal[paletteVal]; + if (val == Character.MAX_VALUE) { + val = ordinal(palette.valueFor(i), adapter); + paletteToOrdinal[i] = val; + } + data[i] = val; + } + } else { + char ordinal = ordinal(palette.valueFor(0), adapter); + Arrays.fill(data, ordinal); + } + } finally { + for (int i = 0; i < num_palette; i++) { + paletteToOrdinal[i] = Character.MAX_VALUE; + } + } + return data; + } catch (IllegalAccessException | InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + lock.release(); + } + } + } + + private char ordinal(BlockState ibd, PaperweightFaweAdapter adapter) { + if (ibd == null) { + return BlockTypesCache.ReservedIDs.AIR; + } else { + return adapter.adaptToChar(ibd); + } + } + + public LevelChunkSection[] getSections(boolean force) { + force &= forceLoadSections; + LevelChunkSection[] tmp = sections; + if (tmp == null || force) { + try { + sectionLock.writeLock().lock(); + tmp = sections; + if (tmp == null || force) { + LevelChunkSection[] chunkSections = getChunk().getSections(); + tmp = new LevelChunkSection[chunkSections.length]; + System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length); + sections = tmp; + } + } finally { + sectionLock.writeLock().unlock(); + } + } + return tmp; + } + + public LevelChunk getChunk() { + LevelChunk levelChunk = this.levelChunk; + if (levelChunk == null) { + synchronized (this) { + levelChunk = this.levelChunk; + if (levelChunk == null) { + this.levelChunk = levelChunk = ensureLoaded(this.serverLevel, chunkX, chunkZ); + } + } + } + return levelChunk; + } + + private void fillLightNibble(char[][] light, LightLayer lightLayer, int minSectionPosition, int maxSectionPosition) { + for (int Y = 0; Y <= maxSectionPosition - minSectionPosition; Y++) { + if (light[Y] == null) { + continue; + } + SectionPos sectionPos = SectionPos.of(levelChunk.getPos(), Y + minSectionPosition); + DataLayer dataLayer = serverLevel.getChunkSource().getLightEngine().getLayerListener(lightLayer).getDataLayerData( + sectionPos); + if (dataLayer == null) { + byte[] LAYER_COUNT = new byte[2048]; + Arrays.fill(LAYER_COUNT, lightLayer == LightLayer.SKY ? (byte) 15 : (byte) 0); + dataLayer = new DataLayer(LAYER_COUNT); + ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( + lightLayer, + sectionPos, + dataLayer + ); + } + synchronized (dataLayer) { + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + int i = y << 8 | z << 4 | x; + if (light[Y][i] < 16) { + dataLayer.set(x, y, z, light[Y][i]); + } + } + } + } + } + } + } + + private PalettedContainer> setBiomesToPalettedContainer( + final BiomeType[][] biomes, + final int sectionIndex, + final PalettedContainerRO> data + ) { + BiomeType[] sectionBiomes; + if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { + return null; + } + PalettedContainer> biomeData = data.recreate(); + for (int y = 0, index = 0; y < 4; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, index++) { + BiomeType biomeType = sectionBiomes[index]; + if (biomeType == null) { + biomeData.set(x, y, z, data.get(x, y, z)); + } else { + biomeData.set( + x, + y, + z, + biomeHolderIdMap.byIdOrThrow(adapter.getInternalBiomeId(biomeType)) + ); + } + } + } + } + return biomeData; + } + + @Override + public boolean hasSection(int layer) { + layer -= getMinSectionPosition(); + return getSections(false)[layer] != null; + } + + @Override + @SuppressWarnings("unchecked") + public synchronized boolean trim(boolean aggressive) { + skyLight = new DataLayer[getSectionCount()]; + blockLight = new DataLayer[getSectionCount()]; + if (aggressive) { + sectionLock.writeLock().lock(); + sections = null; + levelChunk = null; + sectionLock.writeLock().unlock(); + return super.trim(true); + } else if (sections == null) { + // don't bother trimming if there are no sections stored. + return true; + } else { + for (int i = getMinSectionPosition(); i <= getMaxSectionPosition(); i++) { + int layer = i - getMinSectionPosition(); + if (!hasSection(i) || !super.sections[layer].isFull()) { + continue; + } + LevelChunkSection existing = getSections(true)[layer]; + try { + final PalettedContainer blocksExisting = existing.getStates(); + + final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocksExisting); + final Palette palette = (Palette) PaperweightPlatformAdapter.fieldPalette.get( + dataObject); + int paletteSize; + + if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { + paletteSize = palette.getSize(); + } else { + super.trim(false, i); + continue; + } + if (paletteSize == 1) { + //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. + continue; + } + super.trim(false, i); + } catch (IllegalAccessException ignored) { + super.trim(false, i); + } + } + return true; + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks_Copy.java new file mode 100644 index 000000000..60649041b --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightGetBlocks_Copy.java @@ -0,0 +1,276 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.IBlocks; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.util.NbtUtils; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; +import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.PalettedContainerRO; +import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Future; + +public class PaperweightGetBlocks_Copy implements IChunkGet { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); + private final char[][] blocks; + private final int minHeight; + private final int maxHeight; + final ServerLevel serverLevel; + final LevelChunk levelChunk; + private Holder[][] biomes = null; + + protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { + this.levelChunk = levelChunk; + this.serverLevel = levelChunk.level; + this.minHeight = serverLevel.getMinY(); + this.maxHeight = serverLevel.getMaxY() - 1; // Minecraft max limit is exclusive. + this.blocks = new char[getSectionCount()][]; + } + + protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + tiles.put( + BlockVector3.at( + blockEntity.getBlockPos().getX(), + blockEntity.getBlockPos().getY(), + blockEntity.getBlockPos().getZ() + ), + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId(DedicatedServer + .getServer() + .registryAccess()))) + ); + } + + protected void storeEntity(Entity entity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); + entity.save(compoundTag); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); + } + + @Override + public Collection entities() { + return this.entities; + } + + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { + return tag; + } + } + return null; + } + + @Override + public boolean isCreateCopy() { + return false; + } + + @Override + public int setCreateCopy(boolean createCopy) { + return -1; + } + + @Override + public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { + } + + @Override + public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { + } + + @Override + public void setHeightmapToGet(HeightMapType type, int[] data) { + } + + @Override + public int getMaxY() { + return maxHeight; + } + + @Override + public int getMinY() { + return minHeight; + } + + @Override + public int getMaxSectionPosition() { + return maxHeight >> 4; + } + + @Override + public int getMinSectionPosition() { + return minHeight >> 4; + } + + @Override + public BiomeType getBiomeType(int x, int y, int z) { + Holder biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2]; + return PaperweightPlatformAdapter.adapt(biome, serverLevel); + } + + @Override + public void removeSectionLighting(int layer, boolean sky) { + } + + @Override + public boolean trim(boolean aggressive, int layer) { + return false; + } + + @Override + public IBlocks reset() { + return null; + } + + @Override + public int getSectionCount() { + return serverLevel.getSectionsCount(); + } + + protected void storeSection(int layer, char[] data) { + blocks[layer] = data; + } + + protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { + if (biomes == null) { + biomes = new Holder[getSectionCount()][]; + } + if (biomes[layer] == null) { + biomes[layer] = new Holder[64]; + } + if (biomeData instanceof PalettedContainer> palettedContainer) { + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + } else { + LOGGER.error( + "Cannot correctly save biomes to history. Expected class type {} but got {}", + PalettedContainer.class.getSimpleName(), + biomeData.getClass().getSimpleName() + ); + } + } + + @Override + public BaseBlock getFullBlock(int x, int y, int z) { + BlockState state = BlockTypesCache.states[get(x, y, z)]; + return state.toBaseBlock((IBlocks) this, x, y, z); + } + + @Override + public boolean hasSection(int layer) { + layer -= getMinSectionPosition(); + return blocks[layer] != null; + } + + @Override + public char[] load(int layer) { + layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } + return blocks[layer]; + } + + @Override + public char[] loadIfPresent(int layer) { + layer -= getMinSectionPosition(); + return blocks[layer]; + } + + @Override + public BlockState getBlock(int x, int y, int z) { + return BlockTypesCache.states[get(x, y, z)]; + } + + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + + @Override + public int getSkyLight(int x, int y, int z) { + return 0; + } + + @Override + public int getEmittedLight(int x, int y, int z) { + return 0; + } + + @Override + public int[] getHeightMap(HeightMapType type) { + return new int[0]; + } + + @Override + public > T call(IChunkSet set, Runnable finalize) { + return null; + } + + public char get(int x, int y, int z) { + final int layer = (y >> 4) - getMinSectionPosition(); + final int index = (y & 15) << 8 | z << 4 | x; + return blocks[layer][index]; + } + + + @Override + public boolean trim(boolean aggressive) { + return false; + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightMapChunkUtil.java new file mode 100644 index 000000000..e972a9dbc --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightMapChunkUtil.java @@ -0,0 +1,34 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; + +//TODO un-very-break-this +public class PaperweightMapChunkUtil extends MapChunkUtil { + + public PaperweightMapChunkUtil() throws NoSuchFieldException { + fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a")); + fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "b")); + fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "c")); + fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b")); + fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "d")); + fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c")); + fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d")); + fieldX.setAccessible(true); + fieldZ.setAccessible(true); + fieldBitMask.setAccessible(true); + fieldHeightMap.setAccessible(true); + fieldChunkData.setAccessible(true); + fieldBlockEntities.setAccessible(true); + fieldFull.setAccessible(true); + } + + @Override + public ClientboundLevelChunkWithLightPacket createPacket() { + // TODO ??? return new ClientboundLevelChunkPacket(); + throw new UnsupportedOperationException(); + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPlatformAdapter.java new file mode 100644 index 000000000..e7fb1b395 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPlatformAdapter.java @@ -0,0 +1,724 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; +import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; +import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.TaskManager; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.IdMap; +import net.minecraft.core.Registry; +import net.minecraft.network.protocol.game.ClientboundForgetLevelChunkPacket; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.BitStorage; +import net.minecraft.util.SimpleBitStorage; +import net.minecraft.util.ThreadingDetector; +import net.minecraft.util.Unit; +import net.minecraft.util.ZeroBitStorage; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.GlobalPalette; +import net.minecraft.world.level.chunk.HashMapPalette; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.LinearPalette; +import net.minecraft.world.level.chunk.Palette; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.SingleValuePalette; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import org.apache.logging.log4j.Logger; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.CraftChunk; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; + +import static java.lang.invoke.MethodType.methodType; +import static net.minecraft.core.registries.Registries.BIOME; + +public final class PaperweightPlatformAdapter extends NMSAdapter { + + public static final Field fieldData; + + public static final Constructor dataConstructor; + + public static final Field fieldStorage; + public static final Field fieldPalette; + + private static final Field fieldTickingFluidCount; + private static final Field fieldTickingBlockCount; + private static final Field fieldBiomes; + + private static final MethodHandle methodGetVisibleChunk; + + private static final Field fieldThreadingDetector; + private static final Field fieldLock; + + private static final MethodHandle methodRemoveGameEventListener; + private static final MethodHandle methodremoveTickingBlockEntity; + + /* + * This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java + * and is only needed to support 1.19.4 versions before *and* after this change. + */ + private static final MethodHandle CRAFT_CHUNK_GET_HANDLE; + + private static final Field fieldRemove; + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private static Method PAPER_CHUNK_GEN_ALL_ENTITIES; + private static Field SERVER_LEVEL_ENTITY_MANAGER; + + static final MethodHandle PALETTED_CONTAINER_GET; + + static { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d")); + fieldData.setAccessible(true); + + Class dataClazz = fieldData.getType(); + dataConstructor = dataClazz.getDeclaredConstructors()[0]; + dataConstructor.setAccessible(true); + + fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b")); + fieldStorage.setAccessible(true); + fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c")); + fieldPalette.setAccessible(true); + + fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "g")); + fieldTickingFluidCount.setAccessible(true); + fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f")); + fieldTickingBlockCount.setAccessible(true); + Field tmpFieldBiomes; + try { + // Seems it's sometimes biomes and sometimes "i". Idk this is just easier than having to try to deal with it + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes"); // apparently unobf + } catch (NoSuchFieldException ignored) { + tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i"); // apparently obf + } + fieldBiomes = tmpFieldBiomes; + fieldBiomes.setAccessible(true); + + Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( + "getVisibleChunkIfPresent", + "b" + ), long.class); + getVisibleChunkIfPresent.setAccessible(true); + methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent); + + if (!PaperLib.isPaper()) { + fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f")); + fieldThreadingDetector.setAccessible(true); + fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c")); + fieldLock.setAccessible(true); + } else { + // in paper, the used methods are synchronized properly + fieldThreadingDetector = null; + fieldLock = null; + } + + Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( + Refraction.pickName("removeGameEventListener", "a"), + BlockEntity.class, + ServerLevel.class + ); + removeGameEventListener.setAccessible(true); + methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener); + + Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod( + Refraction.pickName( + "removeBlockEntityTicker", + "k" + ), BlockPos.class + ); + removeBlockEntityTicker.setAccessible(true); + methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker); + + fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); + fieldRemove.setAccessible(true); + + try { + Level.class.getDeclaredMethod("moonrise$getEntityLookup"); + PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities"); + PAPER_CHUNK_GEN_ALL_ENTITIES.setAccessible(true); + } catch (NoSuchMethodException ignored) { + // Non-Paper + SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "N")); + SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true); + } + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); + } catch (RuntimeException | Error e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + MethodHandle craftChunkGetHandle; + final MethodType type = methodType(LevelChunk.class); + try { + craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", type); + } catch (NoSuchMethodException | IllegalAccessException e) { + try { + final MethodType newType = methodType(ChunkAccess.class, ChunkStatus.class); + craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", newType); + craftChunkGetHandle = MethodHandles.insertArguments(craftChunkGetHandle, 1, ChunkStatus.FULL); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + CRAFT_CHUNK_GET_HANDLE = craftChunkGetHandle; + } + + static boolean setSectionAtomic( + String worldName, + IntPair pair, + LevelChunkSection[] sections, + LevelChunkSection expected, + LevelChunkSection value, + int layer + ) { + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); + } + + // There is no point in having a functional semaphore for paper servers. + private static final ThreadLocal SEMAPHORE_THREAD_LOCAL = + ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null)); + + static DelegateSemaphore applyLock(LevelChunkSection section) { + if (PaperLib.isPaper()) { + return SEMAPHORE_THREAD_LOCAL.get(); + } + try { + synchronized (section) { + PalettedContainer blocks = section.getStates(); + ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks); + synchronized (currentThreadingDetector) { + Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector); + if (currentLock instanceof DelegateSemaphore delegateSemaphore) { + return delegateSemaphore; + } + DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock); + fieldLock.set(currentThreadingDetector, newLock); + return newLock; + } + } + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) { + if (!PaperLib.isPaper()) { + LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false); + if (nmsChunk != null) { + return nmsChunk; + } + if (Fawe.isMainThread()) { + return serverLevel.getChunk(chunkX, chunkZ); + } + } else { + LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); + if (nmsChunk != null) { + addTicket(serverLevel, chunkX, chunkZ); + return nmsChunk; + } + nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); + if (nmsChunk != null) { + addTicket(serverLevel, chunkX, chunkZ); + return nmsChunk; + } + // Avoid "async" methods from the main thread. + if (Fawe.isMainThread()) { + return serverLevel.getChunk(chunkX, chunkZ); + } + CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); + try { + CraftChunk chunk; + try { + chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + } catch (TimeoutException e) { + String world = serverLevel.getWorld().getName(); + // We've already taken 10 seconds we can afford to wait a little here. + boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + if (loaded) { + LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); + // Retry chunk load + chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + } else { + throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); + } + } + addTicket(serverLevel, chunkX, chunkZ); + return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + } + + private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { + // Ensure chunk is definitely loaded before applying a ticket + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel + .getChunkSource() + .addRegionTicket(ChunkHolderManager.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + } + + public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { + ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap; + try { + return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ)); + } catch (Throwable thr) { + throw new RuntimeException(thr); + } + } + + @SuppressWarnings("deprecation") + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { + ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); + if (chunkHolder == null) { + return; + } + LevelChunk levelChunk; + if (PaperLib.isPaper()) { + // getChunkAtIfLoadedImmediately is paper only + levelChunk = nmsWorld.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); + } else { + levelChunk = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); + } + if (levelChunk == null) { + return; + } + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } + MinecraftServer.getServer().execute(() -> { + try { + ChunkPos pos = levelChunk.getPos(); + // NOTE: the ClientboundForgetLevelChunkPacket packet is required on 1.21.3 + // as the client won't update empty -> non-empty sections properly otherwise + ClientboundForgetLevelChunkPacket forget = new ClientboundForgetLevelChunkPacket(pos); + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, pos).forEach(p -> { + p.connection.send(forget); + p.connection.send(packet); + }); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + } + }); + } + + private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { + return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false); + } + + /* + NMS conversion + */ + public static LevelChunkSection newChunkSection( + final int layer, + final char[] blocks, + CachedBukkitAdapter adapter, + Registry biomeRegistry, + @Nullable PalettedContainer> biomes + ) { + return newChunkSection(layer, null, blocks, adapter, biomeRegistry, biomes); + } + + public static LevelChunkSection newChunkSection( + final int layer, + final Function get, + char[] set, + CachedBukkitAdapter adapter, + Registry biomeRegistry, + @Nullable PalettedContainer> biomes + ) { + if (set == null) { + return newChunkSection(biomeRegistry, biomes); + } + final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get(); + final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get(); + final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get(); + final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get(); + try { + int num_palette; + if (get == null) { + num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, null); + } else { + num_palette = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, get, set, adapter, null); + } + + int bitsPerEntry = MathMan.log2nlz(num_palette - 1); + if (bitsPerEntry > 0 && bitsPerEntry < 5) { + bitsPerEntry = 4; + } else if (bitsPerEntry > 8) { + bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1); + } + + int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes + final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero); + final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong); + + if (num_palette == 1) { + for (int i = 0; i < blockBitArrayEnd; i++) { + blockStates[i] = 0; + } + } else { + final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntryNonZero, 4096, blockStates); + bitArray.fromRaw(blocksCopy); + } + + final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd); + final BitStorage nmsBits; + if (bitsPerEntry == 0) { + nmsBits = new ZeroBitStorage(4096); + } else { + nmsBits = new SimpleBitStorage(bitsPerEntry, 4096, bits); + } + List palette; + if (bitsPerEntry < 9) { + palette = new ArrayList<>(); + for (int i = 0; i < num_palette; i++) { + int ordinal = paletteToBlock[i]; + blockToPalette[ordinal] = Integer.MAX_VALUE; + final BlockState state = BlockTypesCache.states[ordinal]; + palette.add(((PaperweightBlockMaterial) state.getMaterial()).getState()); + } + } else { + palette = List.of(); + } + + // Create palette with data + @SuppressWarnings("deprecation") // constructor is deprecated on paper, but needed to keep compatibility with spigot + final PalettedContainer blockStatePalettedContainer = + new PalettedContainer<>( + Block.BLOCK_STATE_REGISTRY, + PalettedContainer.Strategy.SECTION_STATES, + PalettedContainer.Strategy.SECTION_STATES.getConfiguration(Block.BLOCK_STATE_REGISTRY, bitsPerEntry), + nmsBits, + palette + ); + if (biomes == null) { + IdMap> biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + biomes = new PalettedContainer<>( + biomeHolderIdMap, + biomeHolderIdMap.byIdOrThrow(WorldEditPlugin + .getInstance() + .getBukkitImplAdapter() + .getInternalBiomeId( + BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES + ); + } + + return new LevelChunkSection(blockStatePalettedContainer, biomes); + } catch (final Throwable e) { + throw e; + } finally { + Arrays.fill(blockToPalette, Integer.MAX_VALUE); + Arrays.fill(paletteToBlock, Integer.MAX_VALUE); + Arrays.fill(blockStates, 0); + Arrays.fill(blocksCopy, 0); + } + } + + @SuppressWarnings("deprecation") // Only deprecated in paper + private static LevelChunkSection newChunkSection( + Registry biomeRegistry, + @Nullable PalettedContainer> biomes + ) { + if (biomes == null) { + return new LevelChunkSection(biomeRegistry); + } + PalettedContainer dataPaletteBlocks = new PalettedContainer<>( + Block.BLOCK_STATE_REGISTRY, + Blocks.AIR.defaultBlockState(), + PalettedContainer.Strategy.SECTION_STATES + ); + return new LevelChunkSection(dataPaletteBlocks, biomes); + } + + public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer> biomes) { + try { + fieldBiomes.set(section, biomes); + } catch (IllegalAccessException e) { + LOGGER.error("Could not set biomes to chunk section", e); + } + } + + /** + * Create a new {@link PalettedContainer}. Should only be used if no biome container existed beforehand. + */ + public static PalettedContainer> getBiomePalettedContainer( + BiomeType[] biomes, + IdMap> biomeRegistry + ) { + if (biomes == null) { + return null; + } + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + // Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length + Map> palette = new HashMap<>(); + for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) { + Holder biome; + if (biomeType == null) { + biome = biomeRegistry.byId(adapter.getInternalBiomeId(BiomeTypes.PLAINS)); + } else { + biome = biomeRegistry.byId(adapter.getInternalBiomeId(biomeType)); + } + palette.put(biomeType, biome); + } + int biomeCount = palette.size(); + int bitsPerEntry = MathMan.log2nlz(biomeCount - 1); + Object configuration = PalettedContainer.Strategy.SECTION_STATES.getConfiguration( + new FakeIdMapBiome(biomeCount), + bitsPerEntry + ); + if (bitsPerEntry > 3) { + bitsPerEntry = MathMan.log2nlz(biomeRegistry.size() - 1); + } + PalettedContainer> biomePalettedContainer = new PalettedContainer<>( + biomeRegistry, + biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), + PalettedContainer.Strategy.SECTION_BIOMES + ); + + final Palette> biomePalette; + if (bitsPerEntry == 0) { + biomePalette = new SingleValuePalette<>( + biomePalettedContainer.registry, + biomePalettedContainer, + new ArrayList<>(palette.values()) // Must be modifiable + ); + } else if (bitsPerEntry == 4) { + biomePalette = LinearPalette.create( + 4, + biomePalettedContainer.registry, + biomePalettedContainer, + new ArrayList<>(palette.values()) // Must be modifiable + ); + } else if (bitsPerEntry < 9) { + biomePalette = HashMapPalette.create( + bitsPerEntry, + biomePalettedContainer.registry, + biomePalettedContainer, + new ArrayList<>(palette.values()) // Must be modifiable + ); + } else { + biomePalette = GlobalPalette.create( + bitsPerEntry, + biomePalettedContainer.registry, + biomePalettedContainer, + null // unused + ); + } + + int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes + final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero); + final int arrayLength = MathMan.ceilZero(64f / blocksPerLong); + + + BitStorage bitStorage = bitsPerEntry == 0 ? new ZeroBitStorage(64) : new SimpleBitStorage( + bitsPerEntry, + 64, + new long[arrayLength] + ); + + try { + Object data = dataConstructor.newInstance(configuration, bitStorage, biomePalette); + fieldData.set(biomePalettedContainer, data); + int index = 0; + for (int y = 0; y < 4; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, index++) { + BiomeType biomeType = biomes[index]; + if (biomeType == null) { + continue; + } + Holder biome = biomeRegistry.byId(WorldEditPlugin + .getInstance() + .getBukkitImplAdapter() + .getInternalBiomeId(biomeType)); + if (biome == null) { + continue; + } + biomePalettedContainer.set(x, y, z, biome); + } + } + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + return biomePalettedContainer; + } + + public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException { + fieldTickingFluidCount.setShort(section, (short) 0); + fieldTickingBlockCount.setShort(section, (short) 0); + } + + public static BiomeType adapt(Holder biome, LevelAccessor levelAccessor) { + final Registry biomeRegistry = levelAccessor.registryAccess().lookupOrThrow(BIOME); + if (biomeRegistry.getKey(biome.value()) == null) { + return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN + : null; + } + return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString()); + } + + static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { + try { + if (levelChunk.loaded || levelChunk.level.isClientSide()) { + BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos()); + if (blockEntity != null) { + if (!levelChunk.level.isClientSide) { + methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level); + } + fieldRemove.set(beacon, true); + } + } + methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos()); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + } + + static List getEntities(LevelChunk chunk) { + if (PaperLib.isPaper()) { + try { + //noinspection unchecked + return (List) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level + .moonrise$getEntityLookup() + .getChunk(chunk.locX, chunk.locZ)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Failed to lookup entities [PAPER=true]", e); + } + } + try { + //noinspection unchecked + return ((PersistentEntitySectionManager) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos()); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to lookup entities [PAPER=false]", e); + } + } + + record FakeIdMapBlock(int size) implements IdMap { + + @Override + public int getId(final net.minecraft.world.level.block.state.BlockState entry) { + return 0; + } + + @Nullable + @Override + public net.minecraft.world.level.block.state.BlockState byId(final int index) { + return null; + } + + @Nonnull + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + + } + + record FakeIdMapBiome(int size) implements IdMap { + + @Override + public int getId(final Biome entry) { + return 0; + } + + @Nullable + @Override + public Biome byId(final int index) { + return null; + } + + @Nonnull + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPostProcessor.java new file mode 100644 index 000000000..cbc675ecb --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightPostProcessor.java @@ -0,0 +1,175 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.registry.state.PropertyKey; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; + +import javax.annotation.Nullable; + +public class PaperweightPostProcessor implements IBatchProcessor { + + @Override + public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + return set; + } + + @SuppressWarnings("deprecation") + @Override + public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) { + boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS; + // The PostProcessor shouldn't be added, but just in case + if (!tickFluid) { + return; + } + PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; + layer: + for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { + char[] set = iChunkSet.loadIfPresent(layer); + if (set == null) { + // No edit means no need to process + continue; + } + char[] get = null; + for (int i = 0; i < 4096; i++) { + char ordinal = set[i]; + char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; + boolean fromGet = false; // Used for liquids + if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { + if (get == null) { + get = getBlocks.load(layer); + } + // If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't + // actually being set + if (get == null) { + continue layer; + } + fromGet = true; + ordinal = replacedOrdinal = get[i]; + } + if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { + continue; + } else if (!fromGet) { // if fromGet, don't do the same again + if (get == null) { + get = getBlocks.load(layer); + } + replacedOrdinal = get[i]; + } + boolean ticking = BlockTypesCache.ticking[ordinal]; + boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; + boolean replacedWasLiquid = false; + BlockState replacedState = null; + if (!ticking) { + // If the block being replaced was not ticking, it cannot be a liquid + if (!replacedWasTicking) { + continue; + } + // If the block being replaced is not fluid, we do not need to worry + if (!(replacedWasLiquid = + (replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) { + continue; + } + } + BlockState state = BlockState.getFromOrdinal(ordinal); + boolean liquid = state.getMaterial().isLiquid(); + int x = i & 15; + int y = (i >> 8) & 15; + int z = (i >> 4) & 15; + BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z); + if (liquid || replacedWasLiquid) { + if (liquid) { + addFluid(getBlocks.serverLevel, state, position); + continue; + } + // If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this + // may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up + // being ticked anyway. We only need it to be "hit" once. + if (!wasAdjacentToWater(get, set, i, x, y, z)) { + continue; + } + addFluid(getBlocks.serverLevel, replacedState, position); + } + } + } + } + + @Nullable + @Override + public Extent construct(final Extent child) { + throw new UnsupportedOperationException("Processing only"); + } + + @Override + public ProcessorScope getScope() { + return ProcessorScope.READING_SET_BLOCKS; + } + + private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { + if (set == null || get == null) { + return false; + } + char ordinal; + char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; + if (x > 0 && set[i - 1] != reserved) { + if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { + return true; + } + } + if (x < 15 && set[i + 1] != reserved) { + if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { + return true; + } + } + if (z > 0 && set[i - 16] != reserved) { + if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { + return true; + } + } + if (z < 15 && set[i + 16] != reserved) { + if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { + return true; + } + } + if (y > 0 && set[i - 256] != reserved) { + if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { + return true; + } + } + if (y < 15 && set[i + 256] != reserved) { + return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); + } + return false; + } + + @SuppressWarnings("deprecation") + private boolean isFluid(char ordinal) { + return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); + } + + @SuppressWarnings("deprecation") + private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { + Fluid type; + if (replacedState.getBlockType() == BlockTypes.LAVA) { + type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA; + } else { + type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER; + } + serverLevel.scheduleTick( + position, + type, + type.getTickDelay(serverLevel) + ); + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighter.java new file mode 100644 index 000000000..0542fc641 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighter.java @@ -0,0 +1,80 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.util.Unit; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.status.ChunkPyramid; +import net.minecraft.world.level.chunk.status.ChunkStatus; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.IntConsumer; + +public class PaperweightStarlightRelighter extends StarlightRelighter { + + private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkPyramid.LOADING_PYRAMID + .getStepTo(ChunkStatus.FULL) + .getAccumulatedRadiusOf(ChunkStatus.LIGHT); + + public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + super(serverLevel, queue); + } + + @Override + protected ChunkPos createChunkPos(final long chunkKey) { + return new ChunkPos(chunkKey); + } + + @Override + protected long asLong(final int chunkX, final int chunkZ) { + return ChunkPos.asLong(chunkX, chunkZ); + } + + @Override + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); + } + + protected void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ) { + try { + serverLevel.getChunkSource().getLightEngine().starlight$serverRelightChunks(coords, chunkCallback, processCallback); + } catch (Exception e) { + LOGGER.error("Error occurred on relighting", e); + } + } + + /* + * Allow the server to unload the chunks again. + * Also, if chunk packets are sent delayed, we need to do that here + */ + protected void postProcessChunks(Set coords) { + boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; + for (ChunkPos pos : coords) { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(new IntPair(x, z), serverLevel, x, z); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + } + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighterFactory.java new file mode 100644 index 000000000..597c3a1e7 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightStarlightRelighterFactory.java @@ -0,0 +1,25 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3; + +import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; +import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; +import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; +import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.queue.IQueueExtent; +import com.sk89q.worldedit.world.World; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.CraftWorld; + +import javax.annotation.Nonnull; + +public class PaperweightStarlightRelighterFactory implements RelighterFactory { + + @Override + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + org.bukkit.World w = Bukkit.getWorld(world.getName()); + if (w == null) { + return NullRelighter.INSTANCE; + } + return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue); + } + +} diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/regen/PaperweightRegen.java new file mode 100644 index 000000000..bdde2bcdf --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/regen/PaperweightRegen.java @@ -0,0 +1,298 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_3.regen; + +import com.fastasyncworldedit.bukkit.adapter.Regenerator; +import com.fastasyncworldedit.core.Fawe; +import com.fastasyncworldedit.core.queue.IChunkCache; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.io.file.SafeFiles; +import com.sk89q.worldedit.world.RegenOptions; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.generator.BiomeProvider; + +import javax.annotation.Nonnull; +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static net.minecraft.core.registries.Registries.BIOME; + +public class PaperweightRegen extends Regenerator { + + private static final Field serverWorldsField; + private static final Field paperConfigField; + private static final Field generatorSettingBaseSupplierField; + + + static { + try { + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + Field tmpPaperConfigField; + try { //only present on paper + tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); + tmpPaperConfigField.setAccessible(true); + } catch (Exception e) { + tmpPaperConfigField = null; + } + paperConfigField = tmpPaperConfigField; + + generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( + "settings", "e")); + generatorSettingBaseSupplierField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //runtime + private ServerLevel originalServerWorld; + private ServerLevel freshWorld; + private LevelStorageSource.LevelStorageAccess session; + + private Path tempDir; + + public PaperweightRegen( + World originalBukkitWorld, + Region region, + Extent target, + RegenOptions options + ) { + super(originalBukkitWorld, region, target, options); + } + + @Override + protected void runTasks(final BooleanSupplier shouldKeepTicking) { + while (shouldKeepTicking.getAsBoolean()) { + if (!this.freshWorld.getChunkSource().pollTask()) { + return; + } + } + } + + @Override + protected boolean prepare() { + this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle(); + seed = options.getSeed().orElse(originalServerWorld.getSeed()); + return true; + } + + @Override + protected boolean initNewWorld() throws Exception { + //world folder + tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + + //prepare for world init (see upstream implementation for reference) + org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment(); + org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); + ResourceKey levelStemResourceKey = getWorldDimKey(environment); + session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); + PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; + + MinecraftServer server = originalServerWorld.getCraftServer().getServer(); + WorldOptions originalOpts = originalWorldData.worldGenOptions(); + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) + : originalOpts; + LevelSettings newWorldSettings = new LevelSettings( + "faweregentempworld", + originalWorldData.settings.gameType(), + originalWorldData.settings.hardcore(), + originalWorldData.settings.difficulty(), + originalWorldData.settings.allowCommands(), + originalWorldData.settings.gameRules(), + originalWorldData.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + originalWorldData.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : originalWorldData.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable()); + + BiomeProvider biomeProvider = getBiomeProvider(); + + + //init world + freshWorld = Fawe.instance().getQueueHandler().sync((Supplier) () -> new ServerLevel( + server, + server.executor, + session, + newWorldData, + originalServerWorld.dimension(), + new LevelStem( + originalServerWorld.dimensionTypeRegistration(), + originalServerWorld.getChunkSource().getGenerator() + ), + new RegenNoOpWorldLoadListener(), + originalServerWorld.isDebug(), + seed, + ImmutableList.of(), + false, + originalServerWorld.getRandomSequences(), + environment, + generator, + biomeProvider + ) { + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .lookupOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; + + @Override + public @Nonnull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + if (options.hasBiomeType()) { + return singleBiome; + } + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } + }).get(); + freshWorld.noSave = true; + removeWorldFromWorldsMap(); + newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name + if (paperConfigField != null) { + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); + } + return true; + } + + @Override + protected void cleanup() { + try { + session.close(); + } catch (Exception ignored) { + } + + //shutdown chunk provider + try { + Fawe.instance().getQueueHandler().sync(() -> { + try { + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ignored) { + } + + //remove world from server + try { + Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap); + } catch (Exception ignored) { + } + + //delete directory + try { + SafeFiles.tryHardToDeleteDir(tempDir); + } catch (Exception ignored) { + } + } + + @Override + protected IChunkCache initSourceQueueCache() { + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); + } + + //util + @SuppressWarnings("unchecked") + private void removeWorldFromWorldsMap() { + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { + return switch (env) { + case NETHER -> LevelStem.NETHER; + case THE_END -> LevelStem.END; + default -> LevelStem.OVERWORLD; + }; + } + + private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { + + private RegenNoOpWorldLoadListener() { + } + + @Override + public void updateSpawnPos(@Nonnull ChunkPos spawnPos) { + } + + @Override + public void onStatusChange( + final @Nonnull ChunkPos pos, + @org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status + ) { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + + } + + } + +} diff --git a/worldedit-bukkit/adapters/adapter-legacy/build.gradle.kts b/worldedit-bukkit/adapters/adapter-legacy/build.gradle.kts deleted file mode 100644 index 822c1f70b..000000000 --- a/worldedit-bukkit/adapters/adapter-legacy/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -plugins { - base -} - -artifacts { - add("default", file("./src/main/resources/fastasyncworldedit-adapters.jar")) -} diff --git a/worldedit-bukkit/adapters/adapter-legacy/src/main/resources/fastasyncworldedit-adapters.jar b/worldedit-bukkit/adapters/adapter-legacy/src/main/resources/fastasyncworldedit-adapters.jar deleted file mode 100644 index 9000989ef..000000000 Binary files a/worldedit-bukkit/adapters/adapter-legacy/src/main/resources/fastasyncworldedit-adapters.jar and /dev/null differ diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 01a632fa1..6a6ba7dc2 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -1,9 +1,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import io.papermc.paperweight.userdev.attribute.Obfuscation +import me.modmuss50.mpp.ReleaseType plugins { `java-library` - alias(libs.plugins.minotaur) + alias(libs.plugins.mod.publish.plugin) } project.description = "Bukkit" @@ -36,6 +37,7 @@ repositories { name = "Glaremasters" url = uri("https://repo.glaremasters.me/repository/towny/") } + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO Remove when 4.17.0 is released flatDir { dir(File("src/main/resources")) } } @@ -46,21 +48,26 @@ val localImplementation = configurations.create("localImplementation") { } val adapters = configurations.create("adapters") { - description = "Adapters to include in the JAR" + description = "Adapters to include in the JAR (Mojmap)" isCanBeConsumed = false isCanBeResolved = true shouldResolveConsistentlyWith(configurations["runtimeClasspath"]) attributes { - attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, - if ((project.findProperty("enginehub.obf.none") as String?).toBoolean()) { - objects.named(Obfuscation.NONE) - } else { - objects.named(Obfuscation.OBFUSCATED) - } - ) + attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.NONE)) } } +val adaptersReobf = configurations.create("adaptersReobf") { + description = "Adapters to include in the JAR (Spigot-Mapped)" + isCanBeConsumed = false + isCanBeResolved = true + shouldResolveConsistentlyWith(configurations["runtimeClasspath"]) + attributes { + attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.OBFUSCATED)) + } + extendsFrom(adapters) +} + dependencies { // Modules api(projects.worldeditCore) @@ -140,21 +147,44 @@ tasks.named("jar") { addJarManifest(WorldEditKind.Plugin, includeClasspath = true) -tasks.named("shadowJar") { - dependsOn(project.project(":worldedit-bukkit:adapters").subprojects.map { it.tasks.named("assemble") }) - from(Callable { - adapters.resolve() - .map { f -> - zipTree(f).matching { - exclude("META-INF/") - } - } - }) +tasks.register("reobfShadowJar") { archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}") + configurations = listOf( + project.configurations.runtimeClasspath.get(), // as is done by shadow for the default shadowJar + adaptersReobf + ) + + // as is done by shadow for the default shadowJar + from(sourceSets.main.map { it.output }) + manifest.inheritFrom(tasks.jar.get().manifest) + exclude("META-INF/INDEX.LIST", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", "module-info.class") + + manifest { + attributes( + "FAWE-Plugin-Jar-Type" to "spigot" + ) + } +} + +tasks.named("shadowJar") { + archiveFileName.set("${rootProject.name}-Paper-${project.version}.${archiveExtension.getOrElse("jar")}") + configurations.add(adapters) + manifest { + attributes( + "paperweight-mappings-namespace" to "mojang", + "FAWE-Plugin-Jar-Type" to "mojang" + ) + } +} + +tasks.withType().configureEach { dependencies { // In tandem with not bundling log4j, we shouldn't relocate base package here. // relocate("org.apache.logging", "com.sk89q.worldedit.log4j") relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") + + exclude(dependency("$group:$name")) + include(dependency(":worldedit-core")) include(dependency(":worldedit-libs:bukkit")) // Purposefully not included, we assume (even though no API exposes it) that Log4J will be present at runtime @@ -173,8 +203,9 @@ tasks.named("shadowJar") { relocate("it.unimi.dsi.fastutil", "com.sk89q.worldedit.bukkit.fastutil") { include(dependency("it.unimi.dsi:fastutil")) } + relocate("net.royawesome.jlibnoise", "com.sk89q.worldedit.jlibnoise") relocate("org.incendo.serverlib", "com.fastasyncworldedit.serverlib") { - include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.1")) + include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.6")) } relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") { include(dependency("com.intellectualsites.paster:Paster")) @@ -182,35 +213,71 @@ tasks.named("shadowJar") { relocate("org.lz4", "com.fastasyncworldedit.core.lz4") { include(dependency("org.lz4:lz4-java:1.8.0")) } - relocate("net.kyori", "com.fastasyncworldedit.core.adventure") { - include(dependency("net.kyori:adventure-nbt:4.14.0")) - } relocate("com.zaxxer", "com.fastasyncworldedit.core.math") { - include(dependency("com.zaxxer:SparseBitSet:1.2")) + include(dependency("com.zaxxer:SparseBitSet:1.3")) } relocate("org.anarres", "com.fastasyncworldedit.core.internal.io") { include(dependency("org.anarres:parallelgzip:1.0.5")) } } + + project.project(":worldedit-bukkit:adapters").subprojects.forEach { + dependencies { + include(dependency("${it.group}:${it.name}")) + } + minimize { + exclude(dependency("${it.group}:${it.name}")) + } + } } tasks.named("assemble").configure { dependsOn("shadowJar") + dependsOn("reobfShadowJar") } -tasks { - modrinth { - token.set(System.getenv("MODRINTH_TOKEN")) - projectId.set("fastasyncworldedit") - versionName.set("${project.version}") - versionNumber.set("${project.version}") - versionType.set("release") - uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar")) - gameVersions.addAll(listOf("1.20.1", "1.20", "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.19", "1.18.2", "1.17.1", "1.16" + - ".5")) - loaders.addAll(listOf("paper", "spigot")) - changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" + - "FastAsyncWorldEdit/releases/tag/${project.version}") - syncBodyFrom.set(rootProject.file("README.md").readText()) +publishMods { + displayName.set("${project.version}") + version.set("${project.version}") + type.set(ReleaseType.STABLE) + changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" + + "FastAsyncWorldEdit/releases/tag/${project.version}") + + val common = modrinthOptions { + accessToken.set(System.getenv("MODRINTH_TOKEN")) + projectId.set("z4HZZnLr") + projectDescription.set(rootProject.file("README.md").readText()) } + + // We publish the reobfJar twice to ensure that the modrinth download menu picks the right jar for the platform regardless + // of minecraft version. + + val mojmapPaperVersions = listOf("1.20.6", "1.21.1", "1.21.3") + val spigotMappedPaperVersions = listOf("1.20.2", "1.20.4") + + // Mark reobfJar as spigot only for 1.20.5+ + modrinth("spigot") { + from(common) + file.set(tasks.named("reobfShadowJar").flatMap { it.archiveFile }) + minecraftVersions.set(mojmapPaperVersions) + modLoaders.set(listOf("spigot")) + } + + // Mark reobfJar as spigot & paper for <1.20.5 + modrinth("spigotAndOldPaper") { + from(common) + file.set(tasks.named("reobfShadowJar").flatMap { it.archiveFile }) + minecraftVersions.set(spigotMappedPaperVersions) + modLoaders.set(listOf("paper", "spigot")) + } + + // Mark mojang mapped jar as paper 1.20.5+ only + modrinth { + from(common) + file.set(tasks.named("shadowJar").flatMap { it.archiveFile }) + minecraftVersions.set(mojmapPaperVersions) + modLoaders.set(listOf("paper")) + } + + // dryRun.set(true) // For testing } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index c8945b625..5e60a704c 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -108,14 +108,6 @@ public class FaweBukkit implements IFawe, Listener { if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) { LOGGER.warn("Small-edits enabled (maximum y range of 0 -> 256) with 1.18 world heights. Are you sure?"); } - - if (version.isEqualOrLowerThan(MinecraftVersion.ONE_DOT_SIXTEEN_EOL)) { - LOGGER.warn("You are running Minecraft 1.16.5. This version has been released over two years ago (January 2021)."); - LOGGER.warn("FastAsyncWorldEdit will stop operating on this version in the near future."); - LOGGER.warn("Neither Mojang, nor Spigot or other software vendors support this version anymore." + - "Please update your server to a newer version of Minecraft (1.20+) to continue receiving updates and " + - "support."); - } } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkitWorld.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkitWorld.java new file mode 100644 index 000000000..375351d56 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkitWorld.java @@ -0,0 +1,67 @@ +package com.fastasyncworldedit.bukkit; + +import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; +import com.fastasyncworldedit.bukkit.util.WorldUnloadedException; +import com.fastasyncworldedit.core.math.IntPair; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; + +public class FaweBukkitWorld extends BukkitWorld { + + private static final Map CACHE = Collections.synchronizedMap(new WeakHashMap<>()); + + private final ConcurrentHashMap SENDING_CHUNKS = new ConcurrentHashMap<>(); + + /** + * Construct the object. + * + * @param world the world + */ + private FaweBukkitWorld(final World world) { + super(world); + } + + public static FaweBukkitWorld of(World world) { + return CACHE.compute(world, (__, val) -> { + if (val == null) { + return new FaweBukkitWorld(world); + } + val.updateReference(); + return val; + }); + } + + public static FaweBukkitWorld of(String worldName) { + World world = Bukkit.getWorld(worldName); + if (world == null) { + throw new UnsupportedOperationException("Unable to find org.bukkit.World instance for " + worldName + ". Is it loaded?"); + } + return of(world); + } + + public static ConcurrentHashMap getWorldSendingChunksMap(FaweBukkitWorld world) { + return world.SENDING_CHUNKS; + } + + public static ConcurrentHashMap getWorldSendingChunksMap(String worldName) { + return of(worldName).SENDING_CHUNKS; + } + + private void updateReference() { + World world = getWorld(); + World bukkitWorld = Bukkit.getWorld(worldNameRef); + if (bukkitWorld == null) { + throw new WorldUnloadedException(worldNameRef); + } else if (bukkitWorld != world) { + worldRef = new WeakReference<>(bukkitWorld); + } + } + +} diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitGetBlocks.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitGetBlocks.java index 6096c0ace..8a5cc9d8a 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitGetBlocks.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitGetBlocks.java @@ -2,6 +2,6 @@ package com.fastasyncworldedit.bukkit.adapter; public interface BukkitGetBlocks { - void send(int mask, boolean lighting); + void send(); } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java new file mode 100644 index 000000000..441cd1d87 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java @@ -0,0 +1,85 @@ +package com.fastasyncworldedit.bukkit.adapter; + +import com.fastasyncworldedit.core.util.TaskManager; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.TreeGenerator; +import org.bukkit.Material; +import org.bukkit.TreeType; +import org.bukkit.World; +import org.bukkit.block.BlockState; + +import java.util.List; +import java.util.Map; + +/** + * A base class for version-specific implementations of the BukkitImplAdapter + * + * @param the version-specific NBT tag type + * @param the version-specific ServerLevel type + */ +public abstract class FaweAdapter extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter { + + protected final BukkitImplAdapter parent; + protected char[] ibdToStateOrdinal = null; + protected int[] ordinalToIbdID = null; + protected boolean initialised = false; + protected Map>> allBlockProperties = null; + + protected FaweAdapter(final BukkitImplAdapter parent) { + this.parent = parent; + } + + @Override + public boolean generateTree( + final TreeGenerator.TreeType treeType, + final EditSession editSession, + BlockVector3 blockVector3, + final World world + ) { + TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType); + if (bukkitType == TreeType.CHORUS_PLANT) { + // bukkit skips the feature gen which does this offset normally, so we have to add it back + blockVector3 = blockVector3.add(BlockVector3.UNIT_Y); + } + BlockVector3 target = blockVector3; + SERVER_LEVEL serverLevel = getServerLevel(world); + List placed = TaskManager.taskManager().sync(() -> { + preCaptureStates(serverLevel); + try { + if (!world.generateTree(BukkitAdapter.adapt(world, target), bukkitType)) { + return null; + } + return getCapturedBlockStatesCopy(serverLevel); + } finally { + postCaptureBlockStates(serverLevel); + } + }); + + if (placed == null || placed.isEmpty()) { + return false; + } + for (BlockState blockState : placed) { + if (blockState == null || blockState.getType() == Material.AIR) { + continue; + } + editSession.setBlock(blockState.getX(), blockState.getY(), blockState.getZ(), + BukkitAdapter.adapt(blockState.getBlockData()) + ); + } + return true; + } + + protected abstract void preCaptureStates(SERVER_LEVEL serverLevel); + + protected abstract List getCapturedBlockStatesCopy(SERVER_LEVEL serverLevel); + + protected abstract void postCaptureBlockStates(SERVER_LEVEL serverLevel); + + protected abstract SERVER_LEVEL getServerLevel(World world); + +} diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java index 29162b607..16e959d27 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java @@ -31,6 +31,8 @@ import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.TreeType; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; @@ -97,7 +99,7 @@ public interface IBukkitAdapter { checkNotNull(position); return new org.bukkit.Location( world, - position.getX(), position.getY(), position.getZ() + position.x(), position.y(), position.z() ); } @@ -117,7 +119,7 @@ public interface IBukkitAdapter { checkNotNull(location); return new org.bukkit.Location( world, - location.getX(), location.getY(), location.getZ(), + location.x(), location.y(), location.z(), location.getYaw(), location.getPitch() ); @@ -164,10 +166,10 @@ public interface IBukkitAdapter { */ default Material adapt(ItemType itemType) { checkNotNull(itemType); - if (!itemType.getId().startsWith("minecraft:")) { + if (!itemType.id().startsWith("minecraft:")) { throw new IllegalArgumentException("Bukkit only supports Minecraft items"); } - return Material.getMaterial(itemType.getId().substring(10).toUpperCase(Locale.ROOT)); + return Material.getMaterial(itemType.id().substring(10).toUpperCase(Locale.ROOT)); } /** @@ -178,18 +180,20 @@ public interface IBukkitAdapter { */ default Material adapt(BlockType blockType) { checkNotNull(blockType); - if (!blockType.getId().startsWith("minecraft:")) { + if (!blockType.id().startsWith("minecraft:")) { throw new IllegalArgumentException("Bukkit only supports Minecraft blocks"); } - String id = blockType.getId().substring(10).toUpperCase(Locale.ROOT); + String id = blockType.id().substring(10).toUpperCase(Locale.ROOT); return Material.getMaterial(id); } default org.bukkit.entity.EntityType adapt(EntityType entityType) { - if (!entityType.getId().startsWith("minecraft:")) { - throw new IllegalArgumentException("Bukkit only supports vanilla entities"); + NamespacedKey entityKey = NamespacedKey.fromString(entityType.toString()); + if (entityKey == null) { + throw new IllegalArgumentException("Entity key '" + entityType + "' does not map to Bukkit"); } - return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10).toLowerCase(Locale.ROOT)); + + return Registry.ENTITY_TYPE.get(entityKey); } /** @@ -289,11 +293,11 @@ public interface IBukkitAdapter { } default Biome adapt(BiomeType biomeType) { - if (!biomeType.getId().startsWith("minecraft:")) { + if (!biomeType.id().startsWith("minecraft:")) { throw new IllegalArgumentException("Bukkit only supports vanilla biomes"); } try { - return Biome.valueOf(biomeType.getId().substring(10).toUpperCase(Locale.ROOT)); + return Biome.valueOf(biomeType.id().substring(10).toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException e) { return null; } @@ -343,7 +347,7 @@ public interface IBukkitAdapter { * @return WorldEdit EntityType */ default EntityType adapt(org.bukkit.entity.EntityType entityType) { - return EntityTypes.get(entityType.getName().toLowerCase(Locale.ROOT)); + return EntityTypes.get(entityType.getKey().toString()); } /** diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java index e0d13a36b..41c5cbc79 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java @@ -8,15 +8,13 @@ import com.sk89q.worldedit.bukkit.BukkitPlayer; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; @@ -33,6 +31,8 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; import java.util.Map; @@ -81,7 +81,7 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { } @Override - default void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) { + default void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) { getParent().sendFakeNBT(player, pos, nbtData); } @@ -115,6 +115,26 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { return getParent().getInternalBlockStateId(state); } + @Override + default boolean clearContainerBlockContents(World world, BlockVector3 pt) { + return getParent().clearContainerBlockContents(world, pt); + } + + @Override + default void setBiome(Location location, BiomeType biome) { + getParent().setBiome(location, biome); + } + + @Override + default BiomeType getBiome(Location location) { + return getParent().getBiome(location); + } + + @Override + default void sendBiomeUpdates(World world, Iterable chunks) { + getParent().sendBiomeUpdates(world, chunks); + } + @Override default BlockMaterial getMaterial(BlockType blockType) { return getParent().getMaterial(blockType); @@ -131,8 +151,8 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { } @Override - default BinaryTag toNativeBinary(T foreign) { - return getParent().toNativeBinary(foreign); + default LinTag toNativeLin(T foreign) { + return getParent().toNativeLin(foreign); } @Override @@ -141,8 +161,8 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { } @Override - default T fromNativeBinary(BinaryTag foreign) { - return getParent().fromNativeBinary(foreign); + default T fromNativeLin(LinTag foreign) { + return getParent().fromNativeLin(foreign); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java index c146153fc..f8b240bb9 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java @@ -1,12 +1,17 @@ package com.fastasyncworldedit.bukkit.adapter; +import com.fastasyncworldedit.bukkit.FaweBukkitWorld; import com.fastasyncworldedit.core.FAWEPlatformAdapterImpl; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.ReflectionUtils; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.StampedLock; import java.util.function.Function; public class NMSAdapter implements FAWEPlatformAdapterImpl { @@ -137,7 +142,121 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl { if (!(chunk instanceof BukkitGetBlocks)) { throw new IllegalArgumentException("(IChunkGet) chunk not of type BukkitGetBlocks"); } - ((BukkitGetBlocks) chunk).send(mask, lighting); + ((BukkitGetBlocks) chunk).send(); + } + + /** + * Atomically set the given chunk section to the chunk section array stored in the chunk, given the expected existing chunk + * section instance at the given layer position. + *

+ * Acquires a (FAWE-implemented only) write-lock on the chunk packet lock, waiting if required before writing, then freeing + * the lock. Also sets a boolean to indicate a write is waiting and therefore reads should not occur. + *

+ * Utilises ConcurrentHashMap#compute for easy synchronisation for all of the above. Only tryWriteLock is used in blocks + * synchronised using ConcurrentHashMap methods. + * + * @since 2.12.0 + */ + protected static boolean setSectionAtomic( + String worldName, + IntPair pair, + LevelChunkSection[] sections, + LevelChunkSection expected, + LevelChunkSection value, + int layer + ) { + if (layer < 0 || layer >= sections.length) { + return false; + } + StampLockHolder holder = new StampLockHolder(); + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.compute(pair, (k, lock) -> { + if (lock == null) { + lock = new ChunkSendLock(); + } else if (lock.writeWaiting) { + throw new IllegalStateException("Attempting to write chunk section when write is already ongoing?!"); + } + holder.stamp = lock.lock.tryWriteLock(); + holder.chunkLock = lock; + lock.writeWaiting = true; + return lock; + }); + try { + if (holder.stamp == 0) { + holder.stamp = holder.chunkLock.lock.writeLock(); + } + return ReflectionUtils.compareAndSet(sections, expected, value, layer); + } finally { + chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.computeIfPresent(pair, (k, lock) -> { + if (lock != holder.chunkLock) { + throw new IllegalStateException("SENDING_CHUNKS stored lock does not equal lock attempted to be unlocked?!"); + } + lock.lock.unlockWrite(holder.stamp); + lock.writeWaiting = false; + // Keep the lock, etc. in the map as we're going to be accessing again later when sending + return lock; + }); + } + } + + /** + * Called before sending a chunk packet, filling the given stamp and stampedLock arrays' zeroth indices if the chunk packet + * send should go ahead. + *

+ * Chunk packets should be sent if both of the following are met: + * - There is no more than one current packet send ongoing + * - There is no chunk section "write" waiting or ongoing, + * which are determined by the number of readers currently locking the StampedLock (i.e. the number of sends), if the + * stamped lock is currently write-locked and if the boolean for waiting write is true. + *

+ * Utilises ConcurrentHashMap#compute for easy synchronisation + * + * @since 2.12.0 + */ + protected static void beginChunkPacketSend(String worldName, IntPair pair, StampLockHolder stampedLock) { + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.compute(pair, (k, lock) -> { + if (lock == null) { + lock = new ChunkSendLock(); + } + // Allow twice-read-locking, so if the packets have been created but not sent, we can queue another read + if (lock.writeWaiting || lock.lock.getReadLockCount() > 1 || lock.lock.isWriteLocked()) { + return lock; + } + stampedLock.stamp = lock.lock.readLock(); + stampedLock.chunkLock = lock; + return lock; + }); + } + + /** + * Releases the read lock acquired when sending a chunk packet for a chunk + * + * @since 2.12.0 + */ + protected static void endChunkPacketSend(String worldName, IntPair pair, StampLockHolder lockHolder) { + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.computeIfPresent(pair, (k, lock) -> { + if (lock.lock != lockHolder.chunkLock.lock) { + throw new IllegalStateException("SENDING_CHUNKS stored lock does not equal lock attempted to be unlocked?!"); + } + lock.lock.unlockRead(lockHolder.stamp); + // Do not continue to store the lock if we may not need it (i.e. chunk has been sent, may not be sent again) + return null; + }); + } + + public static final class StampLockHolder { + public long stamp; + public ChunkSendLock chunkLock = null; + } + + public static final class ChunkSendLock { + + public final StampedLock lock = new StampedLock(); + public boolean writeWaiting = false; + } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSRelighterFactory.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSRelighterFactory.java index 4fd78df85..39c327991 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSRelighterFactory.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSRelighterFactory.java @@ -5,7 +5,6 @@ import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; @@ -14,8 +13,7 @@ import javax.annotation.Nonnull; public class NMSRelighterFactory implements RelighterFactory { @Override - public @Nonnull - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { + public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue) { return new NMSRelighter( queue, relightMode != null ? relightMode : RelightMode.valueOf(Settings.settings().LIGHTING.MODE) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java index 7c00ebb2b..ac75a29f6 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java @@ -1,60 +1,32 @@ package com.fastasyncworldedit.bukkit.adapter; -import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import org.apache.logging.log4j.Logger; -import org.bukkit.World; import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.WorldInfo; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; import java.util.function.Function; -import java.util.stream.Collectors; /** * Represents an abstract regeneration handler. - * - * @param the type of the {@code IChunkAccess} of the current Minecraft implementation - * @param the type of the {@code ProtoChunk} of the current Minecraft implementation - * @param the type of the {@code Chunk} of the current Minecraft implementation - * @param the type of the {@code ChunkStatusWrapper} wrapping the {@code ChunkStatus} enum */ -public abstract class Regenerator> { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public abstract class Regenerator { protected final org.bukkit.World originalBukkitWorld; protected final Region region; @@ -62,13 +34,8 @@ public abstract class Regenerator chunkStati = new LinkedHashMap<>(); - private final Long2ObjectLinkedOpenHashMap protoChunks = new Long2ObjectLinkedOpenHashMap<>(); - private final Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap<>(); - protected boolean generateConcurrent = true; protected long seed; - private ExecutorService executor; - private SingleThreadQueueExtent source; + protected SingleThreadQueueExtent source; /** * Initializes an abstract regeneration handler. @@ -85,19 +52,10 @@ public abstract class Regenerator> chunkCoordsForRadius = new Int2ObjectOpenHashMap<>(); - chunkStati.keySet().stream().map(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { - if (radius == -1) { //ignore ChunkStatus.EMPTY - return; - } - int border = 10 - radius; //9 = 8 + 1, 8: max border radius used in chunk stages, 1: need 1 extra chunk for chunk - // features to generate at the border of the region - chunkCoordsForRadius.put(radius, getChunkCoordsRegen(region, border)); - }); - - //create chunks - for (Long xz : chunkCoordsForRadius.get(0)) { - ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz)); - protoChunks.put(xz, chunk); - } - - //generate lists for RegionLimitedWorldAccess, need to be square with odd length (e.g. 17x17), 17 = 1 middle chunk + 8 border chunks * 2 - Int2ObjectOpenHashMap>> worldlimits = new Int2ObjectOpenHashMap<>(); - chunkStati.keySet().stream().map(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { - if (radius == -1) { //ignore ChunkStatus.EMPTY - return; - } - Long2ObjectOpenHashMap> map = new Long2ObjectOpenHashMap<>(); - for (Long xz : chunkCoordsForRadius.get(radius)) { - int x = MathMan.unpairIntX(xz); - int z = MathMan.unpairIntY(xz); - List l = new ArrayList<>((radius + 1 + radius) * (radius + 1 + radius)); - for (int zz = z - radius; zz <= z + radius; zz++) { //order is important, first z then x - for (int xx = x - radius; xx <= x + radius; xx++) { - l.add(protoChunks.get(MathMan.pairInt(xx, zz))); - } - } - map.put(xz, l); - } - worldlimits.put(radius, map); - }); - - //run generation tasks excluding FULL chunk status - for (Map.Entry entry : chunkStati.entrySet()) { - ChunkStatus chunkStatus = entry.getKey(); - int radius = chunkStatus.requiredNeighborChunkRadius0(); - - List coords = chunkCoordsForRadius.get(radius); - if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) { - SequentialTasks>> tasks = getChunkStatusTaskRows(coords, radius); - for (ConcurrentTasks> para : tasks) { - List scheduled = new ArrayList<>(tasks.size()); - for (SequentialTasks row : para) { - scheduled.add(() -> { - for (Long xz : row) { - chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz)); - } - }); - } - try { - List> futures = new ArrayList<>(); - scheduled.forEach(task -> futures.add(executor.submit(task))); - for (Future future : futures) { - future.get(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } else if (this.generateConcurrent && entry.getValue() == Concurrency.FULL) { - // every chunk can be processed individually - List scheduled = new ArrayList<>(coords.size()); - for (long xz : coords) { - scheduled.add(() -> { - chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz)); - }); - } - try { - List> futures = new ArrayList<>(); - scheduled.forEach(task -> futures.add(executor.submit(task))); - for (Future future : futures) { - future.get(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } else { // Concurrency.NONE or generateConcurrent == false - // run sequential but submit to different thread - // running regen on the main thread otherwise triggers async-only events on the main thread - executor.submit(() -> { - for (long xz : coords) { - chunkStatus.processChunkSave(xz, worldlimits.get(radius).get(xz)); - } - }).get(); // wait until finished this step - } - } - - //convert to proper chunks - for (Long xz : chunkCoordsForRadius.get(0)) { - ProtoChunk proto = protoChunks.get(xz); - chunks.put(xz, createChunk(proto)); - } - - //final chunkstatus - ChunkStatus FULL = getFullChunkStatus(); - for (Long xz : chunkCoordsForRadius.get(0)) { //FULL.requiredNeighbourChunkRadius() == 0! - Chunk chunk = chunks.get(xz); - FULL.processChunkSave(xz, Arrays.asList(chunk)); - } - - //populate - List populators = getBlockPopulators(); - for (Long xz : chunkCoordsForRadius.get(0)) { - int x = MathMan.unpairIntX(xz); - int z = MathMan.unpairIntY(xz); - - //prepare chunk seed - Random random = getChunkRandom(seed, x, z); - - //actually populate - Chunk c = chunks.get(xz); - populators.forEach(pop -> { - populate(c, random, pop); - }); - } - - source = new SingleThreadQueueExtent(BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, - BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256); + source = new SingleThreadQueueExtent( + BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, + BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256 + ); source.init(target, initSourceQueueCache(), null); - return true; } private void copyToWorld() { + createSource(); + final long timeoutPerTick = TimeUnit.MILLISECONDS.toNanos(10); + int taskId = TaskManager.taskManager().repeat(() -> { + final long startTime = System.nanoTime(); + runTasks(() -> System.nanoTime() - startTime < timeoutPerTick); + }, 1); //Setting Blocks boolean genbiomes = options.shouldRegenBiomes(); boolean hasBiome = options.hasBiomeType(); @@ -315,6 +117,7 @@ public abstract class Regenerator source.getBiome(vec))); } + TaskManager.taskManager().cancel(taskId); } private class PlacementPattern implements Pattern { @@ -326,7 +129,7 @@ public abstract class Regenerator getBlockPopulators(); - - /** - * Implement the population of the {@code Chunk} with the given chunk random and {@code BlockPopulator} here. - * - * @param chunk the {@code Chunk} to populate - * @param random the chunk random to use for population - * @param pop the {@code BlockPopulator} to use - */ - protected abstract void populate(Chunk chunk, Random random, BlockPopulator pop); - /** * Implement the initialization an {@code IChunkCache} here. Use will need the {@code getChunkAt} function * @@ -436,103 +195,6 @@ public abstract class Regenerator initSourceQueueCache(); - //algorithms - private List getChunkCoordsRegen(Region region, int border) { //needs to be square num of chunks - BlockVector3 oldMin = region.getMinimumPoint(); - BlockVector3 newMin = BlockVector3.at( - (oldMin.getX() >> 4 << 4) - border * 16, - oldMin.getY(), - (oldMin.getZ() >> 4 << 4) - border * 16 - ); - BlockVector3 oldMax = region.getMaximumPoint(); - BlockVector3 newMax = BlockVector3.at( - (oldMax.getX() >> 4 << 4) + (border + 1) * 16 - 1, - oldMax.getY(), - (oldMax.getZ() >> 4 << 4) + (border + 1) * 16 - 1 - ); - Region adjustedRegion = new CuboidRegion(newMin, newMax); - return adjustedRegion.getChunks().stream() - .sorted(Comparator - .comparingInt(BlockVector2::getZ) - .thenComparingInt(BlockVector2::getX)) //needed for RegionLimitedWorldAccess - .map(c -> MathMan.pairInt(c.getX(), c.getZ())) - .collect(Collectors.toList()); - } - - /** - * Creates a list of chunkcoord rows that may be executed concurrently - * - * @param allcoords the coords that should be sorted into rows, must be sorted by z and x - * @param requiredNeighborChunkRadius the radius of neighbor chunks that may not be written to concurrently (ChunkStatus - * .requiredNeighborRadius) - * @return a list of chunkcoords rows that may be executed concurrently - */ - private SequentialTasks>> getChunkStatusTaskRows( - List allcoords, - int requiredNeighborChunkRadius - ) { - int requiredneighbors = Math.max(0, requiredNeighborChunkRadius); - - int minx = allcoords.isEmpty() ? 0 : MathMan.unpairIntX(allcoords.get(0)); - int maxx = allcoords.isEmpty() ? 0 : MathMan.unpairIntX(allcoords.get(allcoords.size() - 1)); - int minz = allcoords.isEmpty() ? 0 : MathMan.unpairIntY(allcoords.get(0)); - int maxz = allcoords.isEmpty() ? 0 : MathMan.unpairIntY(allcoords.get(allcoords.size() - 1)); - SequentialTasks>> tasks; - if (maxz - minz > maxx - minx) { - int numlists = Math.min(requiredneighbors * 2 + 1, maxx - minx + 1); - - Int2ObjectOpenHashMap> byx = new Int2ObjectOpenHashMap(); - int expectedListLength = (allcoords.size() + 1) / (maxx - minx); - - //init lists - for (int i = minx; i <= maxx; i++) { - byx.put(i, new SequentialTasks(expectedListLength)); - } - - //sort into lists by x coord - for (Long xz : allcoords) { - byx.get(MathMan.unpairIntX(xz)).add(xz); - } - - //create parallel tasks - tasks = new SequentialTasks(numlists); - for (int offset = 0; offset < numlists; offset++) { - ConcurrentTasks> para = new ConcurrentTasks((maxz - minz + 1) / numlists + 1); - for (int i = 0; minx + i * numlists + offset <= maxx; i++) { - para.add(byx.get(minx + i * numlists + offset)); - } - tasks.add(para); - } - } else { - int numlists = Math.min(requiredneighbors * 2 + 1, maxz - minz + 1); - - Int2ObjectOpenHashMap> byz = new Int2ObjectOpenHashMap(); - int expectedListLength = (allcoords.size() + 1) / (maxz - minz); - - //init lists - for (int i = minz; i <= maxz; i++) { - byz.put(i, new SequentialTasks(expectedListLength)); - } - - //sort into lists by x coord - for (Long xz : allcoords) { - byz.get(MathMan.unpairIntY(xz)).add(xz); - } - - //create parallel tasks - tasks = new SequentialTasks(numlists); - for (int offset = 0; offset < numlists; offset++) { - ConcurrentTasks> para = new ConcurrentTasks((maxx - minx + 1) / numlists + 1); - for (int i = 0; minz + i * numlists + offset <= maxz; i++) { - para.add(byz.get(minz + i * numlists + offset)); - } - tasks.add(para); - } - } - - return tasks; - } - protected BiomeProvider getBiomeProvider() { if (options.hasBiomeType()) { return new SingleBiomeProvider(); @@ -548,101 +210,6 @@ public abstract class Regenerator the IChunkAccess class of the current Minecraft implementation - */ - public static abstract class ChunkStatusWrapper { - - /** - * Return the required neighbor chunk radius the wrapped {@code ChunkStatus} requires. - * - * @return the radius of required neighbor chunks - */ - public abstract int requiredNeighborChunkRadius(); - - int requiredNeighborChunkRadius0() { - return Math.max(0, requiredNeighborChunkRadius()); - } - - /** - * Return the name of the wrapped {@code ChunkStatus}. - * - * @return the radius of required neighbor chunks - */ - public abstract String name(); - - /** - * Return the name of the wrapped {@code ChunkStatus}. - * - * @param xz represents the chunk coordinates of the chunk to process as denoted by {@code MathMan} - * @param accessibleChunks a list of chunks that will be used during the execution of the wrapped {@code ChunkStatus}. - * This list is order in the correct order required by the {@code ChunkStatus}, unless Mojang suddenly decides to do things differently. - */ - public abstract CompletableFuture processChunk(Long xz, List accessibleChunks); - - void processChunkSave(Long xz, List accessibleChunks) { - try { - processChunk(xz, accessibleChunks).get(); - } catch (Exception e) { - LOGGER.error( - "Error while running " + name() + " on chunk " + MathMan.unpairIntX(xz) + "/" + MathMan.unpairIntY(xz), - e - ); - } - } - - } - - public static class SequentialTasks extends Tasks { - - public SequentialTasks(int expectedsize) { - super(expectedsize); - } - - } - - public static class ConcurrentTasks extends Tasks { - - public ConcurrentTasks(int expectedsize) { - super(expectedsize); - } - - } - - public static class Tasks implements Iterable { - - private final List tasks; - - public Tasks(int expectedsize) { - tasks = new ArrayList(expectedsize); - } - - public void add(T task) { - tasks.add(task); - } - - public List list() { - return tasks; - } - - public int size() { - return tasks.size(); - } - - @Override - public Iterator iterator() { - return tasks.iterator(); - } - - @Override - public String toString() { - return tasks.toString(); - } - - } - public class SingleBiomeProvider extends BiomeProvider { private final org.bukkit.block.Biome biome = BukkitAdapter.adapt(options.getBiomeType()); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java similarity index 55% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java rename to worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java index 397931bc5..02729cfa9 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java @@ -1,9 +1,7 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.fastasyncworldedit.bukkit.adapter; -import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.TaskManager; @@ -12,13 +10,8 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.LongArraySet; import it.unimi.dsi.fastutil.longs.LongIterator; import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.MCUtil; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashSet; @@ -29,28 +22,98 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.function.IntConsumer; -public class PaperweightStarlightRelighter implements Relighter { +/** + * A base class for version-specific implementations of the starlight relighting mechanism + * + * @param the version-specific ServerLevel type + * @param the version-specific ChunkPos type + * @since 2.8.2 + */ +public abstract class StarlightRelighter implements Relighter { + + protected static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32 private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting - private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); - - - private final ServerLevel serverLevel; private final ReentrantLock lock = new ReentrantLock(); private final Long2ObjectLinkedOpenHashMap regions = new Long2ObjectLinkedOpenHashMap<>(); private final ReentrantLock areaLock = new ReentrantLock(); private final NMSRelighter delegate; + protected final SERVER_LEVEL serverLevel; - @SuppressWarnings("rawtypes") - public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { + protected StarlightRelighter(SERVER_LEVEL serverLevel, IQueueExtent queue) { this.serverLevel = serverLevel; this.delegate = new NMSRelighter(queue); } + protected Set convertChunkKeysToChunkPos(LongSet chunks) { + // convert from long keys to ChunkPos + Set coords = new HashSet<>(); + LongIterator iterator = chunks.iterator(); + while (iterator.hasNext()) { + coords.add(createChunkPos(iterator.nextLong())); + } + return coords; + } + + protected abstract CHUNK_POS createChunkPos(long chunkKey); + + protected abstract long asLong(int chunkX, int chunkZ); + + protected abstract CompletableFuture chunkLoadFuture(CHUNK_POS pos); + + protected List> chunkLoadFutures(Set coords) { + List> futures = new ArrayList<>(); + for (final CHUNK_POS coord : coords) { + futures.add(chunkLoadFuture(coord)); + } + return futures; + } + + @NotNull + protected IntConsumer postProcessCallback(Runnable andThen, Set coords) { + return i -> { + if (i != coords.size()) { + LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); + } + // post process chunks on main thread + TaskManager.taskManager().task(() -> postProcessChunks(coords)); + // call callback on our own threads + TaskManager.taskManager().async(andThen); + }; + } + + protected abstract void invokeRelight( + Set coords, + Consumer chunkCallback, + IntConsumer processCallback + ); + + protected abstract void postProcessChunks(Set coords); + + /* + * Processes a set of chunks and runs an action afterwards. + * The action is run async, the chunks are partly processed on the main thread + * (as required by the server). + */ + protected void fixLighting(LongSet chunks, Runnable andThen) { + Set coords = convertChunkKeysToChunkPos(chunks); + TaskManager.taskManager().task(() -> { + // trigger chunk load and apply ticket on main thread + List> futures = chunkLoadFutures(coords); + // collect futures and trigger relight once all chunks are loaded + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> + invokeRelight( + coords, + c -> { + }, // no callback for single chunks required + postProcessCallback(andThen, coords) + ) + ); + }); + } + @Override public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) { areaLock.lock(); @@ -58,23 +121,19 @@ public class PaperweightStarlightRelighter implements Relighter { long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2); // TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH? LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2)); - chunks.add(ChunkPos.asLong(cx, cz)); + chunks.add(asLong(cx, cz)); } finally { areaLock.unlock(); } return true; } - @Override - public void addLightUpdate(int x, int y, int z) { - delegate.addLightUpdate(x, y, z); - } - /* * This method is called "recursively", iterating and removing elements * from the regions linked map. This way, chunks are loaded in batches to avoid * OOMEs. */ + @Override public void fixLightingSafe(boolean sky) { this.areaLock.lock(); @@ -89,77 +148,9 @@ public class PaperweightStarlightRelighter implements Relighter { } } - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ) - ); - }); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback - ) { - try { - serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); - } catch (Exception e) { - LOGGER.error("Error occurred on relighting", e); - } - } - - /* - * Allow the server to unload the chunks again. - * Also, if chunk packets are sent delayed, we need to do that here - */ - private void postProcessChunks(Set coords) { - boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; - for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); - } + @Override + public void addLightUpdate(int x, int y, int z) { + this.delegate.addLightUpdate(x, y, z); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java index 7b9599084..91ec973bb 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java @@ -135,7 +135,7 @@ public abstract class ChunkListener implements Listener { @Deprecated(since = "2.0.0") public void cleanup(Chunk chunk) { for (Entity entity : chunk.getEntities()) { - if (entity.getType() == EntityType.DROPPED_ITEM) { + if (entity.getType() == EntityType.ITEM) { entity.remove(); } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java index 9ac2fd68a..f1baf3d9e 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java @@ -3,7 +3,9 @@ package com.fastasyncworldedit.bukkit.regions; import com.fastasyncworldedit.core.regions.FaweMask; import com.griefdefender.api.GriefDefender; import com.griefdefender.api.claim.Claim; +import com.griefdefender.api.claim.ClaimManager; import com.griefdefender.api.claim.TrustTypes; +import com.griefdefender.lib.flowpowered.math.vector.Vector3i; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -17,8 +19,8 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener private static final Logger LOGGER = LogManagerCompat.getLogger(); - public GriefDefenderFeature(final Plugin GriefDefenderPlugin) { - super(GriefDefenderPlugin.getName()); + public GriefDefenderFeature(final Plugin plugin) { + super(plugin.getName()); LOGGER.info("Plugin 'GriefDefender' found. Using it now."); } @@ -44,9 +46,14 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener ); return new FaweMask(new CuboidRegion(pos1, pos2)) { + private final int[] bounds = new int[]{ + pos1.x(), pos1.y(), pos1.z(), + pos2.x(), pos2.y(), pos2.z() + }; + @Override public boolean isValid(com.sk89q.worldedit.entity.Player wePlayer, MaskType type) { - return isAllowed(player, claim, type); + return validateClaimAgainstCache(claim, bounds) && isAllowed(player, claim, type); } }; } @@ -54,4 +61,20 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener return null; } + private static boolean validateClaimAgainstCache(Claim claim, int[] bounds) { + Vector3i min = claim.getLesserBoundaryCorner(); + Vector3i max = claim.getGreaterBoundaryCorner(); + if (min.getX() != bounds[0] || min.getY() != bounds[1] || min.getZ() != bounds[2]) { + return false; + } + if (max.getX() != bounds[3] || max.getY() != bounds[4] || max.getZ() != bounds[5]) { + return false; + } + final ClaimManager manager = GriefDefender.getCore().getClaimManager(claim.getWorldUniqueId()); + if (manager == null) { + return false; + } + return manager.getClaimByUUID(claim.getUniqueId()) != null; + } + } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/WorldGuardFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/WorldGuardFeature.java index ade2d8258..6a055de05 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/WorldGuardFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/WorldGuardFeature.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.bukkit.regions; +import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.RegionWrapper; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -56,7 +57,7 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener { if (region instanceof ProtectedPolygonalRegion casted) { BlockVector3 max = region.getMaximumPoint(); BlockVector3 min = region.getMinimumPoint(); - return new Polygonal2DRegion(null, casted.getPoints(), min.getBlockY(), max.getBlockY()); + return new Polygonal2DRegion(null, casted.getPoints(), min.y(), max.y()); } return new AdaptedRegion(region); } @@ -158,18 +159,30 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener { @Override public FaweMask getMask(com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) { + if (isWhitelist && Settings.settings().REGION_RESTRICTIONS_OPTIONS.WORLDGUARD_REGION_BLACKLIST) { + return new FaweMask(RegionWrapper.GLOBAL()); + } final Player player = BukkitAdapter.adapt(wePlayer); final LocalPlayer localplayer = this.worldguard.wrapPlayer(player); final Location location = player.getLocation(); final Set regions = this.getRegions(localplayer, location, isWhitelist); if (!regions.isEmpty()) { + RegionManager manager = WorldGuard + .getInstance() + .getPlatform() + .getRegionContainer() + .get(BukkitAdapter.adapt(location.getWorld())); + if (manager == null) { + return null; + } Set result = new HashSet<>(); for (ProtectedRegion myRegion : regions) { if (myRegion.getId().equals("__global__")) { return new FaweMask(RegionWrapper.GLOBAL()) { @Override public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) { - return isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion); + return manager.hasRegion(myRegion.getId()) + && isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion); } }; } else { @@ -185,7 +198,7 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener { public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) { final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player)); for (ProtectedRegion myRegion : regions) { - if (!isAllowed(localplayer, myRegion)) { + if (!manager.hasRegion(myRegion.getId()) || !isAllowed(localplayer, myRegion)) { return false; } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java index 4ef1a3d05..c111ff630 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java @@ -16,6 +16,7 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.function.FlatRegionFunction; @@ -160,6 +161,10 @@ public class FaweDelegateRegionManager { ); editSession.setBlocks(onTop, air); } + + FlatRegionFunction replace = new BiomeReplace(editSession, biome); + FlatRegionVisitor visitor = new FlatRegionVisitor((CuboidRegion) floorRegion, replace, editSession); + Operations.completeLegacy(visitor); } if (hybridPlotWorld.PLOT_SCHEMATIC) { @@ -213,7 +218,6 @@ public class FaweDelegateRegionManager { ) { TaskManager.taskManager().async(() -> { synchronized (FaweDelegateRegionManager.class) { - //todo because of the following code this should probably be in the Bukkit module World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName())); World pos3World = BukkitAdapter.adapt(getWorld(swapPos.getWorldName())); EditSession sessionA = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World) @@ -232,14 +236,16 @@ public class FaweDelegateRegionManager { CuboidRegion regionB = new CuboidRegion( pos3World, swapPos.getBlockVector3(), - swapPos.getBlockVector3().add(pos2.getBlockVector3()).subtract(pos1.getBlockVector3()) + swapPos.getBlockVector3().add(pos2.getBlockVector3().subtract(pos1.getBlockVector3())).withY(pos2.getY()) ); - Clipboard clipA = Clipboard.create(regionA, UUID.randomUUID()); - Clipboard clipB = Clipboard.create(regionB, UUID.randomUUID()); + Clipboard clipA = new BlockArrayClipboard(regionA, UUID.randomUUID()); + Clipboard clipB = new BlockArrayClipboard(regionB, UUID.randomUUID()); ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint()); ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint()); copyA.setCopyingBiomes(true); copyB.setCopyingBiomes(true); + copyA.setCopyingEntities(true); + copyB.setCopyingEntities(true); try { Operations.completeLegacy(copyA); Operations.completeLegacy(copyB); @@ -253,17 +259,16 @@ public class FaweDelegateRegionManager { sessionA.close(); sessionB.close(); } - FaweAPI.fixLighting(pos1World, new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), null, + FaweAPI.fixLighting( + pos1World, + regionA, + null, RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); - FaweAPI.fixLighting(pos1World, new CuboidRegion( - swapPos.getBlockVector3(), - BlockVector3.at( - swapPos.getX() + pos2.getX() - pos1.getX(), - 0, - swapPos.getZ() + pos2.getZ() - pos1.getZ() - ) - ), null, + FaweAPI.fixLighting( + pos1World, + regionB, + null, RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateSchematicHandler.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateSchematicHandler.java index 6cf09da28..5c6f97d21 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateSchematicHandler.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateSchematicHandler.java @@ -3,8 +3,8 @@ package com.fastasyncworldedit.bukkit.regions.plotsquared; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweAPI; import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReader; -import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriterV2; import com.fastasyncworldedit.core.jnbt.CompressedCompoundTag; import com.fastasyncworldedit.core.jnbt.CompressedSchematicTag; import com.fastasyncworldedit.core.util.IOUtil; @@ -29,17 +29,19 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader; -import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import net.jpountz.lz4.LZ4BlockInputStream; import org.anarres.parallelgzip.ParallelGZIPOutputStream; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.stream.LinBinaryIO; import javax.annotation.Nonnull; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; @@ -94,15 +96,15 @@ public class FaweDelegateSchematicHandler { return; } BlockVector3 dimension = schematic.getClipboard().getDimensions(); - final int WIDTH = dimension.getX(); - final int LENGTH = dimension.getZ(); - final int HEIGHT = dimension.getY(); + final int WIDTH = dimension.x(); + final int LENGTH = dimension.z(); + final int HEIGHT = dimension.y(); final int worldHeight = plot.getArea().getMaxGenHeight() - plot.getArea().getMinGenHeight() + 1; // Validate dimensions CuboidRegion region = plot.getLargestRegion(); boolean sizeMismatch = - ((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || ( - (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT + ((region.getMaximumPoint().x() - region.getMinimumPoint().x() + xOffset + 1) < WIDTH) || ( + (region.getMaximumPoint().z() - region.getMinimumPoint().z() + zOffset + 1) < LENGTH) || (HEIGHT > worldHeight); if (!Settings.Schematics.PASTE_MISMATCHES && sizeMismatch) { if (actor != null) { @@ -111,8 +113,8 @@ public class FaweDelegateSchematicHandler { TaskManager.runTask(whenDone); return; } - if (((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || ( - (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT + if (((region.getMaximumPoint().x() - region.getMinimumPoint().x() + xOffset + 1) < WIDTH) || ( + (region.getMaximumPoint().z() - region.getMinimumPoint().z() + zOffset + 1) < LENGTH) || (HEIGHT > worldHeight)) { if (whenDone != null) { TaskManager.runTask(whenDone); @@ -141,7 +143,7 @@ public class FaweDelegateSchematicHandler { } else { y_offset_actual = yOffset + pw.getMinBuildHeight() + editSession.getHighestTerrainBlock(region .getMinimumPoint() - .getX() + 1, region.getMinimumPoint().getZ() + 1, pw.getMinGenHeight(), pw.getMaxGenHeight() + .x() + 1, region.getMinimumPoint().z() + 1, pw.getMinGenHeight(), pw.getMaxGenHeight() ); } } @@ -150,7 +152,7 @@ public class FaweDelegateSchematicHandler { } final BlockVector3 to = BlockVector3 - .at(region.getMinimumPoint().getX() + xOffset, y_offset_actual, region.getMinimumPoint().getZ() + zOffset); + .at(region.getMinimumPoint().x() + xOffset, y_offset_actual, region.getMinimumPoint().z() + zOffset); final Clipboard clipboard = schematic.getClipboard(); clipboard.setOrigin(clipboard.getRegion().getMinimumPoint()); clipboard.paste(editSession, to, true, false, true); @@ -182,7 +184,7 @@ public class FaweDelegateSchematicHandler { try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream( new BufferedOutputStream(new ParallelGZIPOutputStream(stream)))) { - new FastSchematicWriter(output).write(clipboard); + new FastSchematicWriterV2(output).write(clipboard); } } else { try (OutputStream stream = new FileOutputStream(tmp); @@ -194,7 +196,7 @@ public class FaweDelegateSchematicHandler { } else { try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new ParallelGZIPOutputStream(stream))) { - Map map = tag.getValue(); + Map> map = tag.getValue(); output.writeNamedTag("Schematic", map.getOrDefault("Schematic", tag)); } } @@ -226,7 +228,7 @@ public class FaweDelegateSchematicHandler { try { try (ParallelGZIPOutputStream gzip = new ParallelGZIPOutputStream(output)) { try (NBTOutputStream nos = new NBTOutputStream(gzip)) { - Map map = weTag.getValue(); + Map> map = weTag.getValue(); nos.writeNamedTag("Schematic", map.getOrDefault("Schematic", weTag)); } } @@ -239,7 +241,7 @@ public class FaweDelegateSchematicHandler { public Schematic getSchematic(@Nonnull InputStream is) { try { - FastSchematicReader schematicReader = new FastSchematicReader( + FastSchematicReaderV2 schematicReader = new FastSchematicReaderV2( new NBTInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(is))))); Clipboard clip = schematicReader.read(); return new Schematic(clip); @@ -249,8 +251,8 @@ public class FaweDelegateSchematicHandler { return null; } try { - SpongeSchematicReader schematicReader = - new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(is))); + SpongeSchematicV3Reader schematicReader = + new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(new GZIPInputStream(is)))); Clipboard clip = schematicReader.read(); return new Schematic(clip); } catch (IOException e2) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/PlotSquaredFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/PlotSquaredFeature.java index e1ac20617..49955a4fa 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/PlotSquaredFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/PlotSquaredFeature.java @@ -1,6 +1,5 @@ package com.fastasyncworldedit.bukkit.regions.plotsquared; -import com.fastasyncworldedit.core.FaweAPI; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMaskManager; @@ -159,8 +158,8 @@ public class PlotSquaredFeature extends FaweMaskManager { regions = WEManager.getMask(pp); if (regions.size() == 1) { CuboidRegion region = regions.iterator().next(); - if (region.getMinimumPoint().getX() == Integer.MIN_VALUE - && region.getMaximumPoint().getX() == Integer.MAX_VALUE) { + if (region.getMinimumPoint().x() == Integer.MIN_VALUE + && region.getMaximumPoint().x() == Integer.MAX_VALUE) { regions.clear(); } } @@ -174,22 +173,21 @@ public class PlotSquaredFeature extends FaweMaskManager { return null; } + final World world = player.getWorld(); + int min = area != null ? area.getMinBuildHeight() : world.getMinY(); + // PlotSquared uses exclusive max height, WorldEdit uses inclusive max height -> subtract 1 + int max = area != null ? Math.min(world.getMaxY(), area.getMaxBuildHeight() - 1) : world.getMaxY(); Region maskedRegion; if (regions.size() == 1) { - final World world = player.getWorld(); - int min = area != null ? area.getMinBuildHeight() : world.getMinY(); - // PlotSquared uses exclusive max height, WorldEdit uses inclusive max height -> subtract 1 - int max = area != null ? Math.min(world.getMaxY(), area.getMaxBuildHeight() - 1) : world.getMaxY(); final CuboidRegion region = regions.iterator().next(); final BlockVector3 pos1 = BlockVector3.at(region.getMinimumX(), min, region.getMinimumZ()); final BlockVector3 pos2 = BlockVector3.at(region.getMaximumX(), max, region.getMaximumZ()); maskedRegion = new CuboidRegion(pos1, pos2); } else { - World world = FaweAPI.getWorld(area.getWorldName()); List weRegions = regions.stream().map( - r -> new CuboidRegion(world, BlockVector3.at(r.getMinimumX(), r.getMinimumY(), r.getMinimumZ()), - BlockVector3.at(r.getMaximumX(), r.getMaximumY(), r.getMaximumZ()) + r -> new CuboidRegion(world, BlockVector3.at(r.getMinimumX(), min, r.getMinimumZ()), + BlockVector3.at(r.getMaximumX(), max, r.getMaximumZ()) )).collect(Collectors.toList()); maskedRegion = new RegionIntersection(world, weRegions); } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/DoNotMiniseThese.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/DoNotMiniseThese.java index 9916a7d9f..28fb6d990 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/DoNotMiniseThese.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/DoNotMiniseThese.java @@ -1,6 +1,8 @@ package com.fastasyncworldedit.bukkit.util; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.io.FastBufferedInputStream; +import it.unimi.dsi.fastutil.io.FastBufferedOutputStream; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.LongArraySet; import it.unimi.dsi.fastutil.longs.LongIterator; @@ -19,5 +21,7 @@ final class DoNotMiniseThese { private final LongSet d = null; private final Int2ObjectMap e = null; private final Object2ObjectArrayMap f = null; + private final FastBufferedInputStream g = null; + private final FastBufferedOutputStream h = null; } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java index f719d430d..08ee52de6 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/MinecraftVersion.java @@ -13,7 +13,6 @@ import java.util.regex.Pattern; public class MinecraftVersion implements Comparable { public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16); - public static final MinecraftVersion ONE_DOT_SIXTEEN_EOL = new MinecraftVersion(1, 16, 5); public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17); public static final MinecraftVersion CAVES_18 = new MinecraftVersion(1, 18); private static MinecraftVersion current = null; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java index 424325127..c650975c3 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java @@ -20,6 +20,7 @@ package com.sk89q.bukkit.util; import com.sk89q.util.ReflectionUtil; +import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -96,12 +97,11 @@ public class CommandRegistration { return fallbackCommands; } - CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); + CommandMap commandMap = PaperLib.isPaper() ? Bukkit.getCommandMap() : ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); if (commandMap == null) { Bukkit.getServer().getLogger().severe(plugin.getDescription().getName() - + ": Could not retrieve server CommandMap, using fallback instead!"); - fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer()); - Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin); + + ": Could not retrieve server CommandMap"); + throw new IllegalStateException("Failed to retrieve command map, make sure you are running supported server software"); } else { serverCommandMap = commandMap; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java index 41e7e7294..e0a643015 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java @@ -240,7 +240,7 @@ public enum BukkitAdapter { Vector3 position = location; return new org.bukkit.Location( adapt((World) location.getExtent()), - position.getX(), position.getY(), position.getZ(), + position.x(), position.y(), position.z(), location.getYaw(), location.getPitch() ); @@ -258,7 +258,7 @@ public enum BukkitAdapter { checkNotNull(position); return new org.bukkit.Location( world, - position.getX(), position.getY(), position.getZ() + position.x(), position.y(), position.z() ); } @@ -274,7 +274,7 @@ public enum BukkitAdapter { checkNotNull(position); return new org.bukkit.Location( world, - position.getX(), position.getY(), position.getZ() + position.x(), position.y(), position.z() ); } @@ -290,7 +290,7 @@ public enum BukkitAdapter { checkNotNull(location); return new org.bukkit.Location( world, - location.getX(), location.getY(), location.getZ(), + location.x(), location.y(), location.z(), location.getYaw(), location.getPitch() ); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBiomeRegistry.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBiomeRegistry.java index f78e1ae6a..087834f9b 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBiomeRegistry.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBiomeRegistry.java @@ -40,7 +40,7 @@ class BukkitBiomeRegistry implements BiomeRegistry { @Override public Component getRichName(BiomeType biomeType) { return TranslatableComponent.of( - TranslationManager.makeTranslationKey("biome", biomeType.getId()) + TranslationManager.makeTranslationKey("biome", biomeType.id()) ); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index ab1e54491..d2e8246e6 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -45,7 +45,6 @@ import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -61,6 +60,7 @@ import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.permissions.PermissionAttachment; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -162,7 +162,7 @@ public class BukkitPlayer extends AbstractPlayerActor { final PlayerInventory inv = player.getInventory(); ItemStack newItem = BukkitAdapter.adapt(itemStack); TaskManager.taskManager().sync(() -> { - if (itemStack.getType().getId().equalsIgnoreCase(WorldEdit.getInstance().getConfiguration().wandItem)) { + if (itemStack.getType().id().equalsIgnoreCase(WorldEdit.getInstance().getConfiguration().wandItem)) { inv.remove(newItem); } final ItemStack item = player.getInventory().getItemInMainHand(); @@ -242,9 +242,9 @@ public class BukkitPlayer extends AbstractPlayerActor { //FAWE end return TaskManager.taskManager().sync(() -> player.teleport(new Location( finalWorld, - pos.getX(), - pos.getY(), - pos.getZ(), + pos.x(), + pos.y(), + pos.z(), yaw, pitch ))); @@ -267,7 +267,7 @@ public class BukkitPlayer extends AbstractPlayerActor { @Override public void setGameMode(GameMode gameMode) { - player.setGameMode(org.bukkit.GameMode.valueOf(gameMode.getId().toUpperCase(Locale.ROOT))); + player.setGameMode(org.bukkit.GameMode.valueOf(gameMode.id().toUpperCase(Locale.ROOT))); } @Override @@ -422,7 +422,7 @@ public class BukkitPlayer extends AbstractPlayerActor { @Override public > void sendFakeBlock(BlockVector3 pos, B block) { - Location loc = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ()); + Location loc = new Location(player.getWorld(), pos.x(), pos.y(), pos.z()); if (block == null) { player.sendBlockChange(loc, player.getWorld().getBlockAt(loc).getBlockData()); } else { @@ -430,7 +430,7 @@ public class BukkitPlayer extends AbstractPlayerActor { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK && block instanceof BaseBlock) { - CompoundBinaryTag nbt = ((BaseBlock) block).getNbt(); + LinCompoundTag nbt = ((BaseBlock) block).getNbt(); if (nbt != null) { adapter.sendFakeNBT(player, pos, nbt); adapter.sendFakeOP(player); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java index b060d78f8..2ad20fb6f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java @@ -192,6 +192,9 @@ public class BukkitPlayerBlockBag extends BlockBag implements SlottableBlockBag @Override public BaseItem getItem(int slot) { loadInventory(); + if (items[slot] == null) { + return null; + } return BukkitAdapter.adapt(items[slot]); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index 8278142b6..01d84e8ef 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -42,6 +42,7 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.lifecycle.Lifecycled; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.registry.Registries; +import io.papermc.lib.PaperLib; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -229,7 +230,7 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser //FAWE start @Override - public String getId() { + public String id() { return "intellectualsites:bukkit"; } //FAWE end @@ -258,6 +259,14 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser return SUPPORTED_SIDE_EFFECTS; } + @Override + public long getTickCount() { + if (PaperLib.isPaper()) { + return Bukkit.getCurrentTick(); + } + return super.getTickCount(); + } + public void unregisterCommands() { dynamicCommands.unregisterCommands(); } @@ -298,9 +307,6 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser if (!tickFluid) { return null; } - if (Settings.settings().QUEUE.NO_TICK_FASTMODE && fastMode) { - return null; - } return this.plugin.getBukkitImplAdapter().getTickingPostProcessor(); } //FAWE end diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index a9ba45afe..9e4da5401 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -24,12 +24,12 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -118,9 +118,9 @@ public class BukkitWorld extends AbstractWorld { HAS_MIN_Y = temp; } - private WeakReference worldRef; + protected WeakReference worldRef; //FAWE start - private final String worldNameRef; + protected final String worldNameRef; //FAWE end private final WorldNativeAccess worldNativeAccess; @@ -224,7 +224,7 @@ public class BukkitWorld extends AbstractWorld { //FAWE end @Override - public String getId() { + public String id() { return getWorld().getName().replace(" ", "_").toLowerCase(Locale.ROOT); } @@ -247,7 +247,7 @@ public class BukkitWorld extends AbstractWorld { //FAWE start - safe edit region testCoords(pt); //FAWE end - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); + return getWorld().getBlockAt(pt.x(), pt.y(), pt.z()).getLightLevel(); } @Override @@ -284,7 +284,7 @@ public class BukkitWorld extends AbstractWorld { return false; } - Block block = getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + Block block = getWorld().getBlockAt(pt.x(), pt.y(), pt.z()); BlockState state = PaperLib.getBlockState(block, false).getState(); if (!(state instanceof InventoryHolder)) { return false; @@ -327,12 +327,12 @@ public class BukkitWorld extends AbstractWorld { treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_MUSHROOM, TreeType.BROWN_MUSHROOM); for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) { if (treeTypeMapping.get(type) == null) { - LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type); //FAWE start + LOGGER.info("No TreeType mapping for TreeGenerator.TreeType." + type); LOGGER.info("The above message is displayed because your FAWE version is newer than {}" + " and contains features of future minecraft versions which do not exist in {} hence the tree type" + - "{} is not available. This is not an error. This version will work on your version of Minecraft." + - "This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type); + " {} is not available. This is not an error. This version of FAWE will work on your version of " + + " Minecraft. This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type); //FAWE end } } @@ -363,8 +363,8 @@ public class BukkitWorld extends AbstractWorld { //FAWE end World world = getWorld(); //FAWE start - int X = pt.getBlockX() >> 4; - int Z = pt.getBlockZ() >> 4; + int X = pt.x() >> 4; + int Z = pt.z() >> 4; if (Fawe.isMainThread()) { world.getChunkAt(X, Z); } else if (PaperLib.isPaper()) { @@ -413,7 +413,7 @@ public class BukkitWorld extends AbstractWorld { public void fixAfterFastMode(Iterable chunks) { World world = getWorld(); for (BlockVector2 chunkPos : chunks) { - world.refreshChunk(chunkPos.getBlockX(), chunkPos.getBlockZ()); + world.refreshChunk(chunkPos.x(), chunkPos.z()); } } @@ -495,13 +495,13 @@ public class BukkitWorld extends AbstractWorld { //FAWE start - safe edit region testCoords(pt); //FAWE end - getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); + getWorld().getBlockAt(pt.x(), pt.y(), pt.z()).breakNaturally(); } //FAWE start @Override public Collection getBlockDrops(BlockVector3 position) { - return getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()).getDrops().stream() + return getWorld().getBlockAt(position.x(), position.y(), position.z()).getDrops().stream() .map(BukkitAdapter::adapt).collect(Collectors.toList()); } //FAWE end @@ -538,7 +538,7 @@ public class BukkitWorld extends AbstractWorld { } } if (WorldEditPlugin.getInstance().getLocalConfiguration().unsupportedVersionEditing) { - Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + Block bukkitBlock = getWorld().getBlockAt(position.x(), position.y(), position.z()); return BukkitAdapter.adapt(bukkitBlock.getBlockData()); } else { throw new RuntimeException(new UnsupportedVersionEditException()); @@ -562,7 +562,7 @@ public class BukkitWorld extends AbstractWorld { } } } - Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + Block bukkitBlock = getWorld().getBlockAt(position.x(), position.y(), position.z()); bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); return true; } @@ -584,8 +584,8 @@ public class BukkitWorld extends AbstractWorld { if (!Settings.settings().REGION_RESTRICTIONS_OPTIONS.RESTRICT_TO_SAFE_RANGE) { return; } - int x = position.getX(); - int z = position.getZ(); + int x = position.x(); + int z = position.z(); if (x > 30000000 || z > 30000000 || x < -30000000 || z < -30000000) { throw FaweCache.OUTSIDE_SAFE_REGION; } @@ -636,9 +636,9 @@ public class BukkitWorld extends AbstractWorld { testCoords(position); //FAWE end if (HAS_3D_BIOMES) { - return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ())); + return BukkitAdapter.adapt(getWorld().getBiome(position.x(), position.y(), position.z())); } else { - return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockZ())); + return BukkitAdapter.adapt(getWorld().getBiome(position.x(), position.z())); } } @@ -649,9 +649,9 @@ public class BukkitWorld extends AbstractWorld { testCoords(position); //FAWE end if (HAS_3D_BIOMES) { - getWorld().setBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BukkitAdapter.adapt(biome)); + getWorld().setBiome(position.x(), position.y(), position.z(), BukkitAdapter.adapt(biome)); } else { - getWorld().setBiome(position.getBlockX(), position.getBlockZ(), BukkitAdapter.adapt(biome)); + getWorld().setBiome(position.x(), position.z(), BukkitAdapter.adapt(biome)); } return true; } @@ -665,7 +665,7 @@ public class BukkitWorld extends AbstractWorld { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java index 06f8f81ed..8c9db1c3e 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.SessionIdleEvent; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.internal.event.InteractionDebouncer; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; @@ -55,6 +56,7 @@ import java.util.Optional; public class WorldEditListener implements Listener { private final WorldEditPlugin plugin; + private final InteractionDebouncer debouncer; /** * Construct the object. @@ -63,6 +65,7 @@ public class WorldEditListener implements Listener { */ public WorldEditListener(WorldEditPlugin plugin) { this.plugin = plugin; + debouncer = new InteractionDebouncer(plugin.getInternalPlatform()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @@ -128,62 +131,58 @@ public class WorldEditListener implements Listener { */ @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { - if (!plugin.getInternalPlatform().isHookingEvents()) { - return; - } - - if (event.useItemInHand() == Result.DENY) { - return; - } - - if (event.getHand() == EquipmentSlot.OFF_HAND) { + if (!plugin.getInternalPlatform().isHookingEvents() + || event.useItemInHand() == Result.DENY + || event.getHand() == EquipmentSlot.OFF_HAND + || event.getAction() == Action.PHYSICAL) { return; } final Player player = plugin.wrapPlayer(event.getPlayer()); + + if (event.getAction() != Action.LEFT_CLICK_BLOCK) { + Optional previousResult = debouncer.getDuplicateInteractionResult(player); + if (previousResult.isPresent()) { + if (previousResult.get()) { + event.setCancelled(true); + } + return; + } + } + final World world = player.getWorld(); final WorldEdit we = plugin.getWorldEdit(); final Direction direction = BukkitAdapter.adapt(event.getBlockFace()); + final Block clickedBlock = event.getClickedBlock(); + final Location pos = clickedBlock == null ? null : new Location(world, clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); - Action action = event.getAction(); - if (action == Action.LEFT_CLICK_BLOCK) { - final Block clickedBlock = event.getClickedBlock(); - final Location pos = new Location(world, clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); - - if (we.handleBlockLeftClick(player, pos, direction)) { - event.setCancelled(true); - } - - if (we.handleArmSwing(player)) { - event.setCancelled(true); - } - - } else if (action == Action.LEFT_CLICK_AIR) { - - if (we.handleArmSwing(player)) { - event.setCancelled(true); - } - - } else if (action == Action.RIGHT_CLICK_BLOCK) { - final Block clickedBlock = event.getClickedBlock(); - final Location pos = new Location(world, clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); - - if (we.handleBlockRightClick(player, pos, direction)) { - event.setCancelled(true); - } - - if (we.handleRightClick(player)) { - event.setCancelled(true); - } - } else if (action == Action.RIGHT_CLICK_AIR) { - if (we.handleRightClick(player)) { - event.setCancelled(true); - } + boolean result = false; + switch (event.getAction()) { + case LEFT_CLICK_BLOCK: + result = we.handleBlockLeftClick(player, pos, direction) || we.handleArmSwing(player); + break; + case LEFT_CLICK_AIR: + result = we.handleArmSwing(player); + break; + case RIGHT_CLICK_BLOCK: + result = we.handleBlockRightClick(player, pos, direction) || we.handleRightClick(player); + break; + case RIGHT_CLICK_AIR: + result = we.handleRightClick(player); + break; + default: + break; + } + debouncer.setLastInteraction(player, result); + if (result) { + event.setCancelled(true); } } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { + debouncer.clearInteraction(plugin.wrapPlayer(event.getPlayer())); + plugin.getWorldEdit().getEventBus().post(new SessionIdleEvent(new BukkitPlayer.SessionKeyImpl(event.getPlayer()))); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index e881416c5..c11f8bd73 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -32,9 +32,11 @@ import com.sk89q.wepif.PermissionsResolverManager; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditManifest; import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; +import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; @@ -90,7 +92,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.Optional; +import java.util.jar.Attributes; import static com.google.common.base.Preconditions.checkNotNull; import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME; @@ -120,7 +124,6 @@ public class WorldEditPlugin extends JavaPlugin { public void onLoad() { //FAWE start - this.bukkitConsoleCommandSender = new BukkitCommandSender(this, Bukkit.getConsoleSender()); // This is already covered by Spigot, however, a more pesky warning with a proper explanation over "Ambiguous plugin name..." can't hurt. Plugin[] plugins = Bukkit.getServer().getPluginManager().getPlugins(); for (Plugin p : plugins) { @@ -132,30 +135,82 @@ public class WorldEditPlugin extends JavaPlugin { } } //FAWE end + //FAWE start + final Attributes attributes = WorldEditManifest.readAttributes(); + Objects.requireNonNull(attributes, "Could not retrieve manifest attributes"); + final String type = attributes.getValue("FAWE-Plugin-Jar-Type"); + Objects.requireNonNull(type, "Could not determine plugin jar type"); + if (PaperLib.isPaper()) { + if (PaperLib.getMinecraftVersion() < 20 || (PaperLib.getMinecraftVersion() == 20 && PaperLib.getMinecraftPatchVersion() < 5)) { + if (type.equals("mojang") && !Refraction.isMojangMapped()) { + throw new IllegalStateException( + """ + + ********************************************** + ** You are using the wrong FAWE jar for your Minecraft version. + ** Download the correct FAWE jar from Modrinth: https://modrinth.com/plugin/fastasyncworldedit/ + **********************************************""" + ); + } + } else if (PaperLib.getMinecraftVersion() > 20 || (PaperLib.getMinecraftVersion() == 20 && PaperLib.getMinecraftPatchVersion() >= 5)) { + if (type.equals("spigot")) { + LOGGER.warn( + """ + + ********************************************** + ** You are using the Spigot-mapped FAWE jar on a modern Paper version. + ** This will result in slower first-run times and wasted disk space from plugin remapping. + ** Download the Paper FAWE jar from Modrinth to avoid this: https://modrinth.com/plugin/fastasyncworldedit/ + **********************************************""" + ); + } + } + } else { + if (type.equals("mojang")) { + throw new IllegalStateException( + """ + + ********************************************** + ** You are attempting to run the Paper FAWE jar on a Spigot server. + ** Either switch to Paper (https://papermc.io), or download the correct FAWE jar for your platform + ** from Modrinth: https://modrinth.com/plugin/fastasyncworldedit/ + **********************************************""" + ); + } + } + //FAWE end INSTANCE = this; //noinspection ResultOfMethodCallIgnored getDataFolder().mkdirs(); - WorldEdit worldEdit = WorldEdit.getInstance(); - - // Setup platform - platform = new BukkitServerInterface(this, getServer()); - worldEdit.getPlatformManager().register(platform); - //FAWE start - Migrate from config-legacy to worldedit-config migrateLegacyConfig(); //FAWE end //FAWE start - Modify WorldEdit config name config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "worldedit-config.yml"), true), this); + // Load config before we say we've loaded platforms as it is used in listeners of the event + // Load config in onLoad to ensure it is loaded before FAWE settings to allow (inelegant) copying of values across + // where needed + config.load(); //FAWE end + WorldEdit worldEdit = WorldEdit.getInstance(); + + // Setup platform + platform = new BukkitServerInterface(this, getServer()); + worldEdit.getPlatformManager().register(platform); + //FAWE start - Setup permission attachments permissionAttachmentManager = new BukkitPermissionAttachmentManager(this); //FAWE end + //FAWE start - initialise bukkitConsoleCommandSender later + this.bukkitConsoleCommandSender = new BukkitCommandSender(this, Bukkit.getConsoleSender()); + //FAWE end + Path delChunks = Paths.get(getDataFolder().getPath(), DELCHUNKS_FILE_NAME); if (Files.exists(delChunks)) { ChunkDeleter.runFromFile(delChunks, true); @@ -189,8 +244,6 @@ public class WorldEditPlugin extends JavaPlugin { new FaweBukkit(this); //FAWE end - config.load(); // Load config before we say we've loaded platforms as it is used in listeners of the event - WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent()); PermissionsResolverManager.initialize(this); // Setup permission resolver @@ -559,17 +612,17 @@ public class WorldEditPlugin extends JavaPlugin { public BukkitPlayer wrapPlayer(Player player) { //FAWE start - Use cache over returning a direct BukkitPlayer BukkitPlayer wePlayer = getCachedPlayer(player); - if (wePlayer == null) { - synchronized (player) { - wePlayer = getCachedPlayer(player); - if (wePlayer == null) { - wePlayer = new BukkitPlayer(this, player); - player.setMetadata("WE", new FixedMetadataValue(this, wePlayer)); - return wePlayer; - } - } + if (wePlayer != null) { + return wePlayer; + } + synchronized (player) { + BukkitPlayer bukkitPlayer = getCachedPlayer(player); + if (bukkitPlayer == null) { + bukkitPlayer = new BukkitPlayer(this, player); + player.setMetadata("WE", new FixedMetadataValue(this, bukkitPlayer)); + } + return bukkitPlayer; } - return wePlayer; //FAWE end } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index a34494ce5..8fee3b417 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -27,7 +27,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; -import com.sk89q.jnbt.AdventureNBTConverter; +import com.sk89q.jnbt.LinBusConverter; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; @@ -35,14 +35,13 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; @@ -61,6 +60,8 @@ import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; import java.util.Arrays; @@ -110,7 +111,7 @@ public interface BukkitImplAdapter extends IBukkitAdapter { BlockState getBlock(Location location); /** - * Get the block at the given location. + * Get the block with NBT data at the given location. * * @param location the location * @return the block @@ -183,7 +184,7 @@ public interface BukkitImplAdapter extends IBukkitAdapter { * @param pos The position * @param nbtData The NBT Data */ - void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData); + void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData); /** * Make the client think it has operator status. @@ -280,6 +281,46 @@ public interface BukkitImplAdapter extends IBukkitAdapter { throw new UnsupportedOperationException("This adapter does not support clearing block contents."); } + /** + * Set the biome at a location. + * + * @param location the location + * @param biome the new biome + */ + default void setBiome(Location location, BiomeType biome) { + throw new UnsupportedOperationException("This adapter does not support custom biomes."); + } + + /** + * Gets the current biome at a location. + * + * @param location the location + * @return the biome + */ + default BiomeType getBiome(Location location) { + throw new UnsupportedOperationException("This adapter does not support custom biomes."); + } + + /** + * Initialize registries that require NMS access. + */ + default void initializeRegistries() { + + } + + /** + * Sends biome updates for the given chunks. + * + *

This doesn't modify biomes at all, it just sends the current state of the biomes + * in the world to all of the nearby players, updating the visual representation of the + * biomes on their clients.

+ * + * @param world the world + * @param chunks a list of chunk coordinates to send biome updates for + */ + default void sendBiomeUpdates(World world, Iterable chunks) { + } + //FAWE start default BlockMaterial getMaterial(BlockType blockType) { return getMaterial(blockType.getDefaultState()); @@ -291,11 +332,11 @@ public interface BukkitImplAdapter extends IBukkitAdapter { @Deprecated default Tag toNative(T foreign) { - return AdventureNBTConverter.fromAdventure(toNativeBinary(foreign)); + return LinBusConverter.toJnbtTag(toNativeLin(foreign)); } - default BinaryTag toNativeBinary(T foreign) { - return toNative(foreign).asBinaryTag(); + default LinTag toNativeLin(T foreign) { + return toNative(foreign).toLinTag(); } @Deprecated @@ -303,14 +344,14 @@ public interface BukkitImplAdapter extends IBukkitAdapter { if (foreign == null) { return null; } - return fromNativeBinary(foreign.asBinaryTag()); + return fromNativeLin(foreign.toLinTag()); } - default T fromNativeBinary(BinaryTag foreign) { + default T fromNativeLin(LinTag foreign) { if (foreign == null) { return null; } - return fromNative(AdventureNBTConverter.fromAdventure(foreign)); + return fromNative(LinBusConverter.toJnbtTag(foreign)); } @Nullable diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java index 5cf783350..f55029ac4 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -165,9 +165,11 @@ public class BukkitImplLoader { * @throws AdapterLoadException thrown if no adapter could be found */ public BukkitImplAdapter loadAdapter() throws AdapterLoadException { + // FAWE - do not initialize classes on lookup + final ClassLoader classLoader = this.getClass().getClassLoader(); for (String className : adapterCandidates) { try { - Class cls = Class.forName(className); + Class cls = Class.forName(className, false, classLoader); if (cls.isSynthetic()) { continue; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Refraction.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Refraction.java index 025700ace..273853186 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Refraction.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Refraction.java @@ -42,6 +42,10 @@ public class Refraction { return IS_MOJANG_MAPPED ? mojangName : spigotName; } + public static boolean isMojangMapped() { + return IS_MOJANG_MAPPED; + } + private Refraction() { } diff --git a/worldedit-bukkit/src/main/resources/defaults/worldedit-config.yml b/worldedit-bukkit/src/main/resources/defaults/worldedit-config.yml index 8140cade6..b74eaa091 100644 --- a/worldedit-bukkit/src/main/resources/defaults/worldedit-config.yml +++ b/worldedit-bukkit/src/main/resources/defaults/worldedit-config.yml @@ -24,11 +24,13 @@ limits: max-polygonal-points: default: -1 maximum: 20 + # radius, superpickaxe, brush radius are ignored, use FAWE config limits max-radius: -1 max-super-pickaxe-size: 5 max-brush-radius: 100 butcher-radius: default: -1 + # Ignored, use FAWE config limits maximum: -1 disallowed-blocks: - "minecraft:wheat" diff --git a/worldedit-bukkit/src/main/resources/plugin.yml b/worldedit-bukkit/src/main/resources/plugin.yml index b4f845265..282587ce8 100644 --- a/worldedit-bukkit/src/main/resources/plugin.yml +++ b/worldedit-bukkit/src/main/resources/plugin.yml @@ -21,7 +21,7 @@ permissions: default: op children: fawe.bypass.regions: true - fawe.limit.*: true + fawe.limit.unlimited: true fawe.tips: default: op fawe.admin: @@ -135,6 +135,7 @@ permissions: worldedit.brush.options.transform: true worldedit.brush.options.scroll: true worldedit.brush.options.visualize: true + worldedit.tool.none: true worldedit.tool.deltree: true worldedit.tool.farwand: true worldedit.tool.lrbuild: true diff --git a/worldedit-bukkit/src/test/java/com/sk89q/wepif/TestOfflinePermissible.java b/worldedit-bukkit/src/test/java/com/sk89q/wepif/TestOfflinePermissible.java index c63e98663..9415a88f5 100644 --- a/worldedit-bukkit/src/test/java/com/sk89q/wepif/TestOfflinePermissible.java +++ b/worldedit-bukkit/src/test/java/com/sk89q/wepif/TestOfflinePermissible.java @@ -20,6 +20,7 @@ package com.sk89q.wepif; import com.destroystokyo.paper.profile.PlayerProfile; +import io.papermc.paper.persistence.PersistentDataContainerView; import org.bukkit.BanEntry; import org.bukkit.Location; import org.bukkit.Material; @@ -144,6 +145,11 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible { return false; } + @Override + public boolean isConnected() { + return false; + } + @Override public String getName() { return "Tester"; @@ -240,6 +246,11 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible { throw new UnsupportedOperationException("Not supported yet."); } + @Override + public @Nullable Location getRespawnLocation() { + return null; + } + @Override public void incrementStatistic(@Nonnull Statistic statistic) throws IllegalArgumentException { @@ -360,4 +371,9 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible { return null; } + @Override + public @Nullable Location getLocation() { + return null; + } + } diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIBlockRegistry.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIBlockRegistry.java index 1fdb97ae6..01ad15c1e 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIBlockRegistry.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIBlockRegistry.java @@ -68,7 +68,7 @@ public class CLIBlockRegistry extends BundledBlockRegistry { @Override public Map> getProperties(BlockType blockType) { Map properties = - CLIWorldEdit.inst.getFileRegistries().getDataFile().blocks.get(blockType.getId()).properties; + CLIWorldEdit.inst.getFileRegistries().getDataFile().blocks.get(blockType.id()).properties; Maps.EntryTransformer> entryTransform = (key, value) -> createProperty(value.type, key, value.values); return ImmutableMap.copyOf(Maps.transformEntries(properties, entryTransform)); diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java index e9a397b73..4895a2922 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java @@ -115,7 +115,7 @@ class CLIPlatform extends AbstractPlatform { @Override public World matchWorld(World world) { return this.worlds.stream() - .filter(w -> w.getId().equals(world.getId())) + .filter(w -> w.id().equals(world.id())) .findAny() .orElse(null); } diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/package-info.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/package-info.java index 11ccf05d1..60e756259 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/package-info.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/package-info.java @@ -1,6 +1,6 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.cli.AccessPoint + * {@link com.sk89q.worldedit.cli.AccessPoint} */ package com.sk89q.worldedit.cli; diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java index a8190234c..1502fdbf3 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java @@ -19,10 +19,10 @@ package com.sk89q.worldedit.cli.schematic; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.google.common.collect.ImmutableSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -85,7 +85,7 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld //FAWE end @Override - public String getId() { + public String id() { return getName().replace(" ", "_").toLowerCase(Locale.ROOT); } @@ -193,7 +193,7 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index a58230b2c..d5839d99f 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -12,7 +12,7 @@ applyPlatformAndCoreConfiguration() dependencies { constraints { implementation(libs.snakeyaml) { - version { strictly("2.0") } + version { strictly("2.2") } because("Bukkit provides SnakeYaml") } } @@ -46,7 +46,6 @@ dependencies { implementation(libs.findbugs) implementation(libs.rhino) compileOnly(libs.adventureApi) - compileOnlyApi(libs.adventureNbt) compileOnlyApi(libs.adventureMiniMessage) implementation(libs.zstd) { isTransitive = false } compileOnly(libs.paster) @@ -56,10 +55,10 @@ dependencies { antlr(libs.antlr4) implementation(libs.antlr4Runtime) implementation(libs.jsonSimple) { isTransitive = false } + implementation(platform(libs.linBus.bom)) // Tests testRuntimeOnly(libs.log4jCore) - testImplementation(libs.adventureNbt) testImplementation(libs.parallelgzip) } diff --git a/worldedit-core/doctools/build.gradle.kts b/worldedit-core/doctools/build.gradle.kts index 6f2123f20..cf1cf33de 100644 --- a/worldedit-core/doctools/build.gradle.kts +++ b/worldedit-core/doctools/build.gradle.kts @@ -1,16 +1,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.8.20" + kotlin("jvm") version "1.9.23" application } applyCommonConfiguration() -tasks.withType { - kotlinOptions.jvmTarget = "17" -} - application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter") tasks.named("run") { workingDir = rootProject.projectDir diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java index 0420d0994..1f0efe7a1 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java @@ -125,7 +125,7 @@ public class MobSpawnerBlock extends BaseBlock { @Override public CompoundTag getNbtData() { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); values.put("Delay", new ShortTag(delay)); values.put("SpawnCount", new ShortTag(spawnCount)); values.put("SpawnRange", new ShortTag(spawnRange)); @@ -170,7 +170,7 @@ public class MobSpawnerBlock extends BaseBlock { return; } - Map values = rootTag.getValue(); + Map> values = rootTag.getValue(); Tag t = values.get("id"); if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) { diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java index 333c3336b..bf9adfa38 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java @@ -104,7 +104,7 @@ public class SignBlock extends BaseBlock { @Override public CompoundTag getNbtData() { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); if (isLegacy()) { values.put("Text1", new StringTag(text[0])); values.put("Text2", new StringTag(text[1])); @@ -112,7 +112,7 @@ public class SignBlock extends BaseBlock { values.put("Text4", new StringTag(text[3])); } else { ListTag messages = new ListTag(StringTag.class, Arrays.stream(text).map(StringTag::new).collect(Collectors.toList())); - Map frontTextTag = new HashMap<>(); + Map> frontTextTag = new HashMap<>(); frontTextTag.put("messages", messages); values.put("front_text", new CompoundTag(frontTextTag)); } @@ -125,9 +125,9 @@ public class SignBlock extends BaseBlock { return; } - Map values = rootTag.getValue(); + Map> values = rootTag.getValue(); - Tag t; + Tag t; text = new String[]{EMPTY, EMPTY, EMPTY, EMPTY}; diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java index a60ffbc09..a5b405f47 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SkullBlock.java @@ -100,8 +100,8 @@ public class SkullBlock extends BaseBlock { @Override public CompoundTag getNbtData() { - Map values = new HashMap<>(); - Map inner = new HashMap<>(); + Map> values = new HashMap<>(); + Map> inner = new HashMap<>(); inner.put("Name", new StringTag(owner)); values.put(DeprecationUtil.getHeadOwnerKey(), new CompoundTag(inner)); return new CompoundTag(values); @@ -113,7 +113,7 @@ public class SkullBlock extends BaseBlock { return; } - Map values = rootTag.getValue(); + Map> values = rootTag.getValue(); Tag t; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index b4d2816c3..9045d0e0e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.util.CachedTextureUtil; import com.fastasyncworldedit.core.util.CleanTextureUtil; @@ -13,8 +14,8 @@ import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.WEManager; import com.fastasyncworldedit.core.util.task.KeyQueuedExecutorService; +import com.fastasyncworldedit.core.util.task.UUIDKeyQueuedThreadFactory; import com.github.luben.zstd.Zstd; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.internal.util.LogManagerCompat; import net.jpountz.lz4.LZ4Factory; @@ -36,46 +37,43 @@ import java.lang.management.MemoryUsage; import java.util.Date; import java.util.List; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** - * [ WorldEdit action] - * | - * \|/ + * [ WorldEdit action ] + *
* [ EditSession ] - The change is processed (area restrictions, change limit, block type) - * | - * \|/ - * [Block change] - A block change from some location - * | - * \|/ + *
+ * [ Block change ] - A block change from some location + *
* [ Set Queue ] - The SetQueue manages the implementation specific queue - * | - * \|/ + *
* [ Fawe Queue] - A queue of chunks - check if the queue has the chunk for a change - * | - * \|/ + *
* [ Fawe Chunk Implementation ] - Otherwise create a new FaweChunk object which is a wrapper around the Chunk object - * | - * \|/ + *
* [ Execution ] - When done, the queue then sets the blocks for the chunk, performs lighting updates and sends the chunk packet to the clients *

* Why it's faster: - * - The chunk is modified directly rather than through the API - * \ Removes some overhead, and means some processing can be done async - * - Lighting updates are performed on the chunk level rather than for every block - * \ e.g., A blob of stone: only the visible blocks need to have the lighting calculated - * - Block changes are sent with a chunk packet - * \ A chunk packet is generally quicker to create and smaller for large world edits - * - No physics updates - * \ Physics updates are slow, and are usually performed on each block - * - Block data shortcuts - * \ Some known blocks don't need to have the data set or accessed (e.g., air is never going to have data) - * - Remove redundant extents - * \ Up to 11 layers of extents can be removed - * - History bypassing - * \ FastMode bypasses history and means blocks in the world don't need to be checked and recorded + *
The chunk is modified directly rather than through the API + * - Removes some overhead, and means some processing can be done async + *
Lighting updates are performed on the chunk level rather than for every block + * - e.g., A blob of stone: only the visible blocks need to have the lighting calculated + *
Block changes are sent with a chunk packet + * - A chunk packet is generally quicker to create and smaller for large world edits + *
No physics updates + * - Physics updates are slow, and are usually performed on each block + *
Block data shortcuts + * - Some known blocks don't need to have the data set or accessed (e.g., air is never going to have data) + *
Remove redundant extents + * - Up to 11 layers of extents can be removed + *
History bypassing + * - FastMode bypasses history and means blocks in the world don't need to be checked and recorded */ public class Fawe { @@ -91,7 +89,7 @@ public class Fawe { * The platform specific implementation. */ private final IFawe implementation; - private final KeyQueuedExecutorService clipboardExecutor; + private final KeyQueuedExecutorService uuidKeyQueuedExecutorService; private FaweVersion version; private TextureUtil textures; private QueueHandler queueHandler; @@ -105,6 +103,8 @@ public class Fawe { * Implementation dependent stuff */ this.setupConfigs(); + FaweLimit.MAX.CONFIRM_LARGE = + Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS; TaskManager.IMP = this.implementation.getTaskManager(); TaskManager.taskManager().async(() -> { @@ -137,14 +137,13 @@ public class Fawe { }, 0); TaskManager.taskManager().repeat(timer, 1); - - clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor( + uuidKeyQueuedExecutorService = new KeyQueuedExecutorService<>(new ThreadPoolExecutor( 1, Settings.settings().QUEUE.PARALLEL_THREADS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), - new ThreadFactoryBuilder().setNameFormat("fawe-clipboard-%d").build() + new UUIDKeyQueuedThreadFactory() )); } @@ -362,6 +361,18 @@ public class Fawe { Settings.settings().QUEUE.PARALLEL_THREADS ); } + if (Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT && Settings.settings().HISTORY.USE_DATABASE) { + LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + LOGGER.warn("!!! !!!"); + LOGGER.warn("!!! Using history database whilst deleting disk history! !!!"); + LOGGER.warn("!!! You will not be able to rollback edits after a user logs !!!"); + LOGGER.warn("!!! out, recommended to disable delete-disk-on-logout if you !!!"); + LOGGER.warn("!!! you want to have full history rollback functionality. !!!"); + LOGGER.warn("!!! Disable use-database if you do not need to have rollback !!!"); + LOGGER.warn("!!! functionality and wish to disable this warning. !!!"); + LOGGER.warn("!!! !!!"); + LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + } try { byte[] in = new byte[0]; byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in); @@ -448,9 +459,58 @@ public class Fawe { * * @return Executor used for clipboard IO if clipboard on disk is enabled or null * @since 2.6.2 + * @deprecated Use any of {@link Fawe#submitUUIDKeyQueuedTask(UUID, Runnable)}, + * {@link Fawe#submitUUIDKeyQueuedTask(UUID, Runnable, Object)}, {@link Fawe#submitUUIDKeyQueuedTask(UUID, Callable)} + * to ensure if a thread is already a UUID-queued thread, the task is immediately run */ + @Deprecated(forRemoval = true, since = "2.12.1") public KeyQueuedExecutorService getClipboardExecutor() { - return this.clipboardExecutor; + return this.uuidKeyQueuedExecutorService; + } + + /** + * Submit a task to the UUID key-queued executor + * + * @return Future representing the tank + * @since 2.12.1 + */ + public Future submitUUIDKeyQueuedTask(UUID uuid, Runnable runnable) { + if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) { + runnable.run(); + return CompletableFuture.completedFuture(null); + } + return this.uuidKeyQueuedExecutorService.submit(uuid, runnable); + } + + /** + * Submit a task to the UUID key-queued executor + * + * @return Future representing the tank + * @since 2.12.1 + */ + public Future submitUUIDKeyQueuedTask(UUID uuid, Runnable runnable, T result) { + if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) { + runnable.run(); + return CompletableFuture.completedFuture(result); + } + return this.uuidKeyQueuedExecutorService.submit(uuid, runnable, result); + } + + /** + * Submit a task to the UUID key-queued executor + * + * @return Future representing the tank + * @since 2.12.1 + */ + public Future submitUUIDKeyQueuedTask(UUID uuid, Callable callable) { + if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) { + try { + return CompletableFuture.completedFuture(callable.call()); + } catch (Throwable t) { + return CompletableFuture.failedFuture(t); + } + } + return this.uuidKeyQueuedExecutorService.submit(uuid, callable); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweAPI.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweAPI.java index 4c5339017..28367a949 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweAPI.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweAPI.java @@ -116,7 +116,10 @@ public class FaweAPI { * @param file the file to load * @return a clipboard containing the schematic * @see ClipboardFormat + * @deprecated Opens streams that are not then closed. Use {@link ClipboardFormats#findByFile(File)} and its relevant + * methods to allow closing created streams/closing the reader (which will close the stream(s)) */ + @Deprecated(forRemoval = true, since = "2.11.1") public static Clipboard load(File file) throws IOException { return ClipboardFormats.findByFile(file).load(file); } @@ -339,11 +342,11 @@ public class FaweAPI { final BlockVector3 bot = selection.getMinimumPoint(); final BlockVector3 top = selection.getMaximumPoint(); - final int minX = bot.getBlockX() >> 4; - final int minZ = bot.getBlockZ() >> 4; + final int minX = bot.x() >> 4; + final int minZ = bot.z() >> 4; - final int maxX = top.getBlockX() >> 4; - final int maxZ = top.getBlockZ() >> 4; + final int maxX = top.x() >> 4; + final int maxZ = top.z() >> 4; int count = 0; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java index af14624df..3ed494298 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java @@ -18,6 +18,7 @@ import com.fastasyncworldedit.core.util.collection.CleanableThreadLocal; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; @@ -48,7 +49,6 @@ import java.util.Map.Entry; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -60,16 +60,17 @@ import java.util.function.Supplier; import static com.google.common.base.Preconditions.checkNotNull; public enum FaweCache implements Trimable { - /** - * @deprecated Use {@link #INSTANCE} to get an instance. - */ - @Deprecated(forRemoval = true, since = "2.0.0") - IMP, /** * @since 2.0.0 */ INSTANCE; + /** + * @deprecated Use {@link #INSTANCE} to get an instance. + */ + @Deprecated(forRemoval = true, since = "2.0.0") + public static final FaweCache IMP = INSTANCE; + private static final Logger LOGGER = LogManagerCompat.getLogger(); public final int BLOCKS_PER_LAYER = 4096; @@ -191,17 +192,22 @@ public enum FaweCache implements Trimable { Type.OUTSIDE_REGION ); public static final FaweException MAX_CHECKS = new FaweException( - Caption.of("fawe.cancel.reason.max" + ".checks"), + Caption.of("fawe.cancel.reason.max.checks"), + Type.MAX_CHECKS, + true + ); + public static final FaweException MAX_FAILS = new FaweException( + Caption.of("fawe.cancel.reason.max.fails"), Type.MAX_CHECKS, true ); public static final FaweException MAX_CHANGES = new FaweException( - Caption.of("fawe.cancel.reason.max" + ".changes"), + Caption.of("fawe.cancel.reason.max.changes"), Type.MAX_CHANGES, false ); public static final FaweException LOW_MEMORY = new FaweException( - Caption.of("fawe.cancel.reason.low" + ".memory"), + Caption.of("fawe.cancel.reason.low.memory"), Type.LOW_MEMORY, false ); @@ -531,7 +537,7 @@ public enum FaweCache implements Trimable { } public CompoundTag asTag(Map value) { - HashMap map = new HashMap<>(); + HashMap> map = new HashMap<>(); for (Map.Entry entry : value.entrySet()) { Object child = entry.getValue(); Tag tag = asTag(child); @@ -611,12 +617,38 @@ public enum FaweCache implements Trimable { /* Thread stuff */ + + /** + * Create a new blocking executor with default name and FaweCache logger + * + * @return new blocking executor + */ public ThreadPoolExecutor newBlockingExecutor() { + return newBlockingExecutor("FAWE Blocking Executor - %d"); + } + + /** + * Create a new blocking executor with specified name and FaweCache logger + * + * @return new blocking executor + * @since 2.9.0 + */ + public ThreadPoolExecutor newBlockingExecutor(String name) { + return newBlockingExecutor(name, LOGGER); + } + + /** + * Create a new blocking executor with specified name and logger + * + * @return new blocking executor + * @since 2.9.0 + */ + public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) { int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS; ArrayBlockingQueue queue = new ArrayBlockingQueue<>(nThreads, true); return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, queue, - Executors.defaultThreadFactory(), + new ThreadFactoryBuilder().setNameFormat(name).build(), new ThreadPoolExecutor.CallerRunsPolicy() ) { @@ -651,10 +683,10 @@ public enum FaweCache implements Trimable { int hash = throwable.getMessage() != null ? throwable.getMessage().hashCode() : 0; if (hash != lastException) { lastException = hash; - LOGGER.catching(throwable); + logger.catching(throwable); count = 0; } else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) { - LOGGER.warn(throwable.getMessage()); + logger.warn(throwable.getMessage()); count++; } } @@ -664,10 +696,10 @@ public enum FaweCache implements Trimable { private void handleFaweException(FaweException e) { FaweException.Type type = e.getType(); if (e.getType() == FaweException.Type.OTHER) { - LOGGER.catching(e); + logger.catching(e); } else if (!faweExceptionReasonsUsed[type.ordinal()]) { faweExceptionReasonsUsed[type.ordinal()] = true; - LOGGER.warn("FaweException: " + e.getMessage()); + logger.warn("FaweException: " + e.getMessage()); } } }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/BlendBall.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/BlendBall.java index 902e48a9b..ec3e0766e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/BlendBall.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/BlendBall.java @@ -50,9 +50,9 @@ public class BlendBall implements Brush { final int outsetSize = (int) (size + 1); double brushSizeSquared = size * size; - int tx = position.getBlockX(); - int ty = position.getBlockY(); - int tz = position.getBlockZ(); + int tx = position.x(); + int ty = position.y(); + int tz = position.z(); int[] frequency = new int[BlockTypes.size()]; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CatenaryBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CatenaryBrush.java index e380e74b0..7ad15cef4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CatenaryBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CatenaryBrush.java @@ -81,9 +81,9 @@ public class CatenaryBrush implements Brush, ResettableTool { return pos1.add(pos2).divide(2).toBlockPoint(); } double curveLen = pos1.distance(pos2) * lenPercent; - double dy = pos2.getY() - pos1.getY(); - double dx = pos2.getX() - pos1.getX(); - double dz = pos2.getZ() - pos1.getZ(); + double dy = pos2.y() - pos1.y(); + double dx = pos2.x() - pos1.x(); + double dz = pos2.z() - pos1.z(); double dh = Math.sqrt(dx * dx + dz * dz); double g = Math.sqrt(curveLen * curveLen - dy * dy) / 2; double a = 0.00001; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CommandBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CommandBrush.java index 227960c1d..b71578b55 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CommandBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CommandBrush.java @@ -54,9 +54,9 @@ public class CommandBrush implements Brush { position.subtract(radius, radius, radius), position.add(radius, radius, radius) ); - String replaced = command.replace("{x}", Integer.toString(position.getBlockX())) - .replace("{y}", Integer.toString(position.getBlockY())) - .replace("{z}", Integer.toString(position.getBlockZ())) + String replaced = command.replace("{x}", Integer.toString(position.x())) + .replace("{y}", Integer.toString(position.y())) + .replace("{z}", Integer.toString(position.z())) .replace("{world}", editSession.getWorld().getName()) .replace("{size}", Integer.toString(radius)); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CopyPastaBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CopyPastaBrush.java index 4aeb2daeb..1b60124cb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CopyPastaBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/CopyPastaBrush.java @@ -65,11 +65,11 @@ public class CopyPastaBrush implements Brush, ResettableTool { mask = Masks.alwaysTrue(); } final ResizableClipboardBuilder builder = new ResizableClipboardBuilder(editSession.getWorld()); - final int minY = position.getBlockY(); + final int minY = position.y(); mask = new AbstractDelegateMask(mask) { @Override public boolean test(BlockVector3 vector) { - if (super.test(vector) && vector.getBlockY() >= minY) { + if (super.test(vector) && vector.y() >= minY) { BaseBlock block = editSession.getFullBlock(vector); if (!block.getBlockType().getMaterial().isAir()) { builder.add(vector, BlockTypes.AIR.getDefaultState().toBaseBlock(), block); @@ -91,7 +91,7 @@ public class CopyPastaBrush implements Brush, ResettableTool { newClipboard.setOrigin(position); ClipboardHolder holder = new ClipboardHolder(newClipboard); session.setClipboard(holder); - int blocks = builder.size(); + long blocks = builder.longSize(); player.print(Caption.of("fawe.worldedit.copy.command.copy", blocks)); } else { AffineTransform transform = null; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ErodeBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ErodeBrush.java index 13490dc2f..da52bf504 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ErodeBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ErodeBrush.java @@ -63,15 +63,15 @@ public class ErodeBrush implements Brush { Clipboard buffer1 = new CPUOptimizedClipboard(region); Clipboard buffer2 = new CPUOptimizedClipboard(region); - final int bx = target.getBlockX(); - final int by = target.getBlockY(); - final int bz = target.getBlockZ(); + final int bx = target.x(); + final int by = target.y(); + final int bz = target.z(); - for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { + for (int x = -brushSize, relx = 0; x <= brushSize && relx < buffer1.getWidth(); x++, relx++) { int x0 = x + bx; - for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { + for (int y = -brushSize, rely = 0; y <= brushSize && rely < buffer1.getHeight(); y++, rely++) { int y0 = y + by; - for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { + for (int z = -brushSize, relz = 0; z <= brushSize && relz < buffer1.getLength(); z++, relz++) { int z0 = z + bz; BlockState state = es.getBlock(x0, y0, z0); buffer1.setBlock(relx, rely, relz, state); @@ -106,7 +106,7 @@ public class ErodeBrush implements Brush { for (BlockVector3 pos : finalBuffer) { BlockState block = pos.getBlock(finalBuffer); - es.setBlock(pos.getX() + bx - brushSize, pos.getY() + by - brushSize, pos.getZ() + bz - brushSize, block); + es.setBlock(pos.x() + bx - brushSize, pos.y() + by - brushSize, pos.z() + bz - brushSize, block); } } @@ -115,11 +115,11 @@ public class ErodeBrush implements Brush { Clipboard current, Clipboard target ) { int[] frequency = null; - for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { + for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) { int x2 = x * x; - for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { + for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) { int x2y2 = x2 + z * z; - for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { + for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) { int cube = x2y2 + y * y; target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz)); if (cube >= brushSizeSquared) { @@ -139,9 +139,9 @@ public class ErodeBrush implements Brush { int highest = 1; for (BlockVector3 offs : FACES_TO_CHECK) { BaseBlock next = current.getFullBlock( - relx + offs.getBlockX(), - rely + offs.getBlockY(), - relz + offs.getBlockZ() + relx + offs.x(), + rely + offs.y(), + relz + offs.z() ); if (!next.getBlockType().getMaterial().isMovementBlocker()) { continue; @@ -166,11 +166,11 @@ public class ErodeBrush implements Brush { Clipboard current, Clipboard target ) { int[] frequency = null; - for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { + for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) { int x2 = x * x; - for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { + for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) { int x2y2 = x2 + z * z; - for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { + for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) { int cube = x2y2 + y * y; target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz)); if (cube >= brushSizeSquared) { @@ -190,9 +190,9 @@ public class ErodeBrush implements Brush { int total = 0; for (BlockVector3 offs : FACES_TO_CHECK) { BaseBlock next = current.getFullBlock( - relx + offs.getBlockX(), - rely + offs.getBlockY(), - relz + offs.getBlockZ() + relx + offs.x(), + rely + offs.y(), + relz + offs.z() ); if (next.getMaterial().isMovementBlocker()) { continue; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/FallingSphere.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/FallingSphere.java index fd720c54e..d54bbebb6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/FallingSphere.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/FallingSphere.java @@ -12,9 +12,9 @@ public class FallingSphere implements Brush { @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { - int px = position.getBlockX(); - int py = position.getBlockY(); - int pz = position.getBlockZ(); + int px = position.x(); + int py = position.y(); + int pz = position.z(); int maxY = editSession.getMaxY(); int minY = editSession.getMinY(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/HeightBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/HeightBrush.java index fea4884f1..2c6ea5ec0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/HeightBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/HeightBrush.java @@ -53,7 +53,7 @@ public class HeightBrush implements Brush { try { heightMap = ScalableHeightMap.fromPNG(stream); } catch (IOException e) { - throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid")); + throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid", e.getMessage())); } } else if (clipboard != null) { heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java index 662212981..1ef2a27fa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java @@ -14,7 +14,6 @@ import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; -import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; @@ -25,7 +24,6 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; -import org.apache.logging.log4j.Logger; import java.io.IOException; import java.util.Iterator; @@ -74,10 +72,15 @@ public class InspectBrush extends BrushTool { return false; } try { - BlockVector3 target = getTarget(player, rightClick).toBlockPoint(); - final int x = target.getBlockX(); - final int y = target.getBlockY(); - final int z = target.getBlockZ(); + Vector3 targetVector = getTarget(player, rightClick); + if (targetVector == null) { + player.print(Caption.of("worldedit.tool.no-block")); + return true; + } + BlockVector3 target = targetVector.toBlockPoint(); + final int x = target.x(); + final int y = target.y(); + final int z = target.z(); World world = player.getWorld(); RollbackDatabase db = DBHandler.dbHandler().getDatabase(world); int count = 0; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/PopulateSchem.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/PopulateSchem.java index b28d7536b..59fc2add2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/PopulateSchem.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/PopulateSchem.java @@ -24,7 +24,8 @@ public record PopulateSchem(Mask mask, List clipboards, int rar CuboidRegion cuboid = new CuboidRegion( editSession.getWorld(), position.subtract(size1, size1, size1), - position.add(size1, size1, size1) + position.add(size1, size1, size1), + true ); try { editSession.addSchems(cuboid, mask, clipboards, rarity, randomRotate); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RecurseBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RecurseBrush.java index 869d45150..f87fee30e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RecurseBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RecurseBrush.java @@ -35,7 +35,7 @@ public record RecurseBrush(boolean dfs) implements Brush { DFSRecursiveVisitor visitor = new DFSRecursiveVisitor(mask, replace, Integer.MAX_VALUE, Integer.MAX_VALUE) { @Override public boolean isVisitable(BlockVector3 from, BlockVector3 to) { - int y = to.getBlockY(); + int y = to.y(); return y < maxY && radMask.test(to) && super.isVisitable(from, to); } }; @@ -45,7 +45,7 @@ public record RecurseBrush(boolean dfs) implements Brush { RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, radius, editSession.getMinY(), editSession.getMaxY()) { @Override public boolean isVisitable(BlockVector3 from, BlockVector3 to) { - int y = to.getBlockY(); + int y = to.y(); return y < maxY && super.isVisitable(from, to); } }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RockBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RockBrush.java index 4196a7e11..27937b836 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RockBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/RockBrush.java @@ -19,15 +19,15 @@ public record RockBrush(double amplitude, double frequency, Vector3 radius) impl double seedY = ThreadLocalRandom.current().nextDouble(); double seedZ = ThreadLocalRandom.current().nextDouble(); - int px = position.getBlockX(); - int py = position.getBlockY(); - int pz = position.getBlockZ(); + int px = position.x(); + int py = position.y(); + int pz = position.z(); double distort = this.frequency / size; - double modX = 1D / radius.getX(); - double modY = 1D / radius.getY(); - double modZ = 1D / radius.getZ(); + double modX = 1D / radius.x(); + double modY = 1D / radius.y(); + double modZ = 1D / radius.z(); int radiusSqr = (int) (size * size); int sizeInt = (int) size * 2; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterBrush.java index 7ea15e421..26cf07558 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterBrush.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.function.mask.RadiusMask; import com.fastasyncworldedit.core.function.mask.SurfaceMask; import com.fastasyncworldedit.core.math.BlockVectorSet; import com.fastasyncworldedit.core.math.LocalBlockVectorSet; +import com.fastasyncworldedit.core.util.collection.BlockVector3Set; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.command.tool.brush.Brush; @@ -64,16 +65,17 @@ public class ScatterBrush implements Brush { length = 1; visited.add(position); } - LocalBlockVectorSet placed = new LocalBlockVectorSet(); - placed.setOffset(position.getX(), position.getZ()); + BlockVector3 patternSize = pattern.size(); + BlockVector3Set placed = BlockVector3Set.getAppropriateVectorSet(patternSize.add(distance, distance, distance)); + placed.setOffset(position.x(), position.y(), position.z()); int maxFails = 1000; for (int i = 0; i < count; i++) { int index = ThreadLocalRandom.current().nextInt(length); BlockVector3 pos = visited.get(index); if (pos != null && canApply(pos)) { - int x = pos.getBlockX(); - int y = pos.getBlockY(); - int z = pos.getBlockZ(); + int x = pos.x(); + int y = pos.y(); + int z = pos.z(); if (placed.containsRadius(x, y, z, distance)) { if (maxFails-- <= 0) { break; @@ -88,7 +90,20 @@ public class ScatterBrush implements Brush { finish(editSession, placed, position, pattern, size); } + /** + * @deprecated Use {@link ScatterBrush#finish(EditSession, BlockVector3Set, BlockVector3, Pattern, double)} + */ + @Deprecated(forRemoval = true, since = "2.9.2") public void finish(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pos, Pattern pattern, double size) { + finish(editSession, (BlockVector3Set) placed, pos, pattern, size); + } + + /** + * Complete the scatter brush process. + * + * @since 2.9.2 + */ + public void finish(EditSession editSession, BlockVector3Set placed, BlockVector3 pos, Pattern pattern, double size) { } public boolean canApply(BlockVector3 pos) { @@ -99,8 +114,23 @@ public class ScatterBrush implements Brush { return surface.direction(pt); } + + /** + * @deprecated Use {@link ScatterBrush#apply(EditSession, BlockVector3Set, BlockVector3, Pattern, double)} + */ + @Deprecated(forRemoval = true, since = "2.9.2") public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws MaxChangedBlocksException { + apply(editSession, (BlockVector3Set) placed, pt, p, size); + } + + /** + * Apply the scatter brush to a given position + * + * @since 2.9.2 + */ + public void apply(EditSession editSession, BlockVector3Set placed, BlockVector3 pt, Pattern p, double size) throws + MaxChangedBlocksException { editSession.setBlock(pt, p); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterCommand.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterCommand.java index 1d7841355..9e2c16555 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterCommand.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterCommand.java @@ -45,9 +45,9 @@ public class ScatterCommand extends ScatterBrush { position.subtract(radius, radius, radius), position.add(radius, radius, radius) ); - String replaced = command.replace("{x}", Integer.toString(position.getBlockX())) - .replace("{y}", Integer.toString(position.getBlockY())) - .replace("{z}", Integer.toString(position.getBlockZ())) + String replaced = command.replace("{x}", Integer.toString(position.x())) + .replace("{y}", Integer.toString(position.y())) + .replace("{z}", Integer.toString(position.z())) .replace("{world}", editSession.getWorld().getName()) .replace("{size}", Integer.toString(radius)); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterOverlayBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterOverlayBrush.java index cd7ce9aaa..d6a991234 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterOverlayBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ScatterOverlayBrush.java @@ -16,9 +16,9 @@ public class ScatterOverlayBrush extends ScatterBrush { @Override public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws MaxChangedBlocksException { - final int x = pt.getBlockX(); - final int y = pt.getBlockY(); - final int z = pt.getBlockZ(); + final int x = pt.x(); + final int y = pt.y(); + final int z = pt.z(); BlockVector3 dir = getDirection(pt); if (dir == null) { getDir: @@ -37,7 +37,7 @@ public class ScatterOverlayBrush extends ScatterBrush { return; } } - editSession.setBlock(x + dir.getBlockX(), y + dir.getBlockY(), z + dir.getBlockZ(), p); + editSession.setBlock(x + dir.x(), y + dir.y(), z + dir.z(), p); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ShatterBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ShatterBrush.java index 58fdb4997..196b71f50 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ShatterBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/ShatterBrush.java @@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.command.tool.brush; import com.fastasyncworldedit.core.function.mask.SurfaceMask; import com.fastasyncworldedit.core.math.LocalBlockVectorSet; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.util.collection.BlockVector3Set; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.function.mask.Mask; @@ -24,7 +25,7 @@ public class ShatterBrush extends ScatterBrush { @Override public void apply( final EditSession editSession, - final LocalBlockVectorSet placed, + final BlockVector3Set placed, final BlockVector3 position, Pattern p, double size @@ -34,7 +35,7 @@ public class ShatterBrush extends ScatterBrush { @Override public void finish( EditSession editSession, - LocalBlockVectorSet placed, + BlockVector3Set placed, final BlockVector3 position, Pattern pattern, double size @@ -79,13 +80,13 @@ public class ShatterBrush extends ScatterBrush { } for (int i1 = 0; i1 < BreadthFirstSearch.DIAGONAL_DIRECTIONS.length; i1++) { BlockVector3 direction = BreadthFirstSearch.DIAGONAL_DIRECTIONS[i1]; - int x2 = x + direction.getBlockX(); - int y2 = y + direction.getBlockY(); - int z2 = z + direction.getBlockZ(); + int x2 = x + direction.x(); + int y2 = y + direction.y(); + int z2 = z + direction.z(); // Check boundary - int dx = position.getBlockX() - x2; - int dy = position.getBlockY() - y2; - int dz = position.getBlockZ() - z2; + int dx = position.x() - x2; + int dy = position.y() - y2; + int dz = position.z() - z2; int dSqr = (dx * dx) + (dy * dy) + (dz * dz); if (dSqr <= radius2) { BlockVector3 bv = mutable.setComponents(x2, y2, z2); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SplineBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SplineBrush.java index 55d8fd96a..e1fa38708 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SplineBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SplineBrush.java @@ -130,9 +130,9 @@ public class SplineBrush implements Brush, ResettableTool { private Vector3 getCentroid(Collection points) { MutableVector3 sum = new MutableVector3(); for (BlockVector3 p : points) { - sum.mutX(sum.getX() + p.getX()); - sum.mutY(sum.getY() + p.getY()); - sum.mutZ(sum.getZ() + p.getZ()); + sum.mutX(sum.x() + p.x()); + sum.mutY(sum.y() + p.y()); + sum.mutZ(sum.z() + p.z()); } return sum.multiply(1.0 / points.size()); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SurfaceSpline.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SurfaceSpline.java index f652c4f94..8c94e76ad 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SurfaceSpline.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/SurfaceSpline.java @@ -38,16 +38,16 @@ public class SurfaceSpline implements Brush { int minY = editSession.getMinY(); if (path.isEmpty() || !pos.equals(path.get(path.size() - 1))) { int max = editSession.getNearestSurfaceTerrainBlock( - pos.getBlockX(), - pos.getBlockZ(), - pos.getBlockY(), + pos.x(), + pos.z(), + pos.y(), minY, maxY ); if (max == -1) { return; } - path.add(BlockVector3.at(pos.getBlockX(), max, pos.getBlockZ())); + path.add(BlockVector3.at(pos.x(), max, pos.z())); if (editSession.getActor() != null) { editSession.getActor().print(Caption.of("fawe.worldedit.brush.spline.primary.2")); } @@ -69,9 +69,9 @@ public class SurfaceSpline implements Brush { LocalBlockVectorSet vset = new LocalBlockVectorSet(); for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) { final Vector3 tipv = interpol.getPosition(loop); - final int tipx = MathMan.roundInt(tipv.getX()); - final int tipz = (int) tipv.getZ(); - int tipy = MathMan.roundInt(tipv.getY()); + final int tipx = MathMan.roundInt(tipv.x()); + final int tipz = (int) tipv.z(); + int tipy = MathMan.roundInt(tipv.y()); tipy = editSession.getNearestSurfaceTerrainBlock(tipx, tipz, tipy, minY, maxY, Integer.MIN_VALUE, Integer.MAX_VALUE); if (tipy == Integer.MIN_VALUE || tipy == Integer.MAX_VALUE) { continue; @@ -88,15 +88,15 @@ public class SurfaceSpline implements Brush { LocalBlockVectorSet newSet = new LocalBlockVectorSet(); final int ceilrad = (int) Math.ceil(radius); for (BlockVector3 v : vset) { - final int tipx = v.getBlockX(); - final int tipz = v.getBlockZ(); + final int tipx = v.x(); + final int tipz = v.z(); for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) { for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) { if (MathMan.hypot2(loopx - tipx, 0, loopz - tipz) <= radius2) { int y = editSession.getNearestSurfaceTerrainBlock( loopx, loopz, - v.getBlockY(), + v.y(), minY, maxY, Integer.MIN_VALUE, diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/Scroll.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/Scroll.java index dd7c23984..8e34d3996 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/Scroll.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/Scroll.java @@ -51,6 +51,7 @@ public abstract class Scroll implements ScrollTool { parserContext.setActor(player); parserContext.setWorld(player.getWorld()); parserContext.setSession(session); + parserContext.setTryLegacy(player.getLimit().ALLOW_LEGACY); switch (mode) { case CLIPBOARD: if (arguments.size() != 2) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollRange.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollRange.java index 405b62b81..db33a526f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollRange.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollRange.java @@ -13,7 +13,7 @@ public class ScrollRange extends Scroll { @Override public boolean increment(Player player, int amount) { - int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius; + int max = player.getLimit().MAX_BRUSH_RADIUS; int newSize = MathMan.wrap(getTool().getRange() + amount, (int) (getTool().getSize() + 1), max); getTool().setRange(newSize); return true; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollSize.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollSize.java index cf60639f5..ac34226f2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollSize.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/scroll/ScrollSize.java @@ -12,7 +12,7 @@ public class ScrollSize extends Scroll { @Override public boolean increment(Player player, int amount) { - int max = WorldEdit.getInstance().getConfiguration().maxRadius; + int max = player.getLimit().MAX_RADIUS; double newSize = Math.max(0, Math.min(max == -1 ? 4095 : max, getTool().getSize() + amount)); getTool().setSize(newSize); return true; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/ClipboardSpline.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/ClipboardSpline.java index 87f1495f5..281c78c74 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/ClipboardSpline.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/ClipboardSpline.java @@ -83,7 +83,7 @@ public class ClipboardSpline extends Spline { Region region = clipboard.getRegion(); BlockVector3 origin = clipboard.getOrigin(); // center = region.getCenter().setY(origin.getY() - 1); - center = region.getCenter().withY(origin.getY() - 1).toBlockPoint(); + center = region.getCenter().withY(origin.y() - 1).toBlockPoint(); this.centerOffset = center.subtract(center.round()); this.center = center.subtract(centerOffset); this.transform = transform; @@ -108,15 +108,15 @@ public class ClipboardSpline extends Spline { clipboardHolder.setTransform(transform); BlockVector3 functionOffset = target.subtract(clipboard.getOrigin()); - final int offX = functionOffset.getBlockX(); - final int offY = functionOffset.getBlockY(); - final int offZ = functionOffset.getBlockZ(); + final int offX = functionOffset.x(); + final int offY = functionOffset.y(); + final int offZ = functionOffset.z(); Operation operation = clipboardHolder .createPaste(editSession) .to(target) .ignoreAirBlocks(true) - .filter(v -> buffer.add(v.getBlockX() + offX, v.getBlockY() + offY, v.getBlockZ() + offZ)) + .filter(v -> buffer.add(v.x() + offX, v.y() + offY, v.z() + offZ)) .build(); Operations.completeLegacy(operation); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/Spline.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/Spline.java index 945c10f5a..872ec495e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/Spline.java @@ -121,7 +121,7 @@ public abstract class Spline { * 2 dimensional "cross" product. cross2D(v1, v2) = |v1|*|v2|*sin(theta) or v1 X v2 taking Y to be 0 */ private double cross2D(Vector2 v1, Vector2 v2) { - return v1.getX() * v2.getZ() - v2.getX() * v1.getZ(); + return v1.x() * v2.z() - v2.x() * v1.z(); } /** @@ -144,7 +144,7 @@ public abstract class Spline { // Calculate rotation from spline Vector3 deriv = interpolation.get1stDerivative(position); - Vector2 deriv2D = Vector2.at(deriv.getX(), deriv.getZ()).normalize(); + Vector2 deriv2D = Vector2.at(deriv.x(), deriv.z()).normalize(); double angle = Math.toDegrees( -Math.atan2(cross2D(direction, deriv2D), direction.dot(deriv2D)) ); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/SweepBrush.java index fa4bb971c..603fb4302 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/sweep/SweepBrush.java @@ -79,13 +79,13 @@ public class SweepBrush implements Brush, ResettableTool { Clipboard clipboard = holder.getClipboard(); BlockVector3 dimensions = clipboard.getDimensions(); - double quality = Math.max(dimensions.getBlockX(), dimensions.getBlockZ()); + double quality = Math.max(dimensions.x(), dimensions.z()); AffineTransform transform = new AffineTransform(); ClipboardSpline spline = new ClipboardSpline(editSession, holder, interpol, transform, nodes.size()); - if (dimensions.getBlockX() > dimensions.getBlockZ()) { + if (dimensions.x() > dimensions.z()) { spline.setDirection(Vector2.at(0, 1)); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java index bc300d584..880b4cdf7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java @@ -2,9 +2,11 @@ package com.fastasyncworldedit.core.configuration; import com.fastasyncworldedit.core.configuration.file.YamlConfiguration; import com.fastasyncworldedit.core.util.StringMan; +import com.sk89q.util.StringUtil; import com.sk89q.worldedit.internal.util.LogManagerCompat; import org.apache.logging.log4j.Logger; +import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintWriter; @@ -14,8 +16,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.util.AbstractMap; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -27,8 +32,16 @@ public class Config { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private final Map removedKeyVals = new HashMap<>(); + @Nullable + private Map> copyTo = new HashMap<>(); + private boolean performCopyTo = false; + private List existingMigrateNodes = null; + public Config() { - save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0); + // This is now definitely required as the save -> load -> save order means the @CopiedFrom annotated fields work + save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0, null); + performCopyTo = true; } /** @@ -43,7 +56,8 @@ public class Config { try { return (T) field.get(instance); } catch (IllegalAccessException e) { - e.printStackTrace(); + LOGGER.error("Failed to get config option: {}", key, e); + return null; } } } @@ -53,11 +67,12 @@ public class Config { /** * Set the value of a specific node. Probably throws some error if you supply non existing keys or invalid values. + * This should only be called during loading of a config file * * @param key config node * @param value value */ - private void set(String key, Object value, Class root) { + private void setLoadedNode(String key, Object value, Class root) { String[] split = key.split("\\."); Object instance = getInstance(split, root); if (instance != null) { @@ -67,6 +82,20 @@ public class Config { if (field.getAnnotation(Final.class) != null) { return; } + if (copyTo != null) { + copyTo.remove(key); // Remove if the config field is already written + final Object finalValue = value; + copyTo.replaceAll((copyToNode, entry) -> { + if (!key.equals(entry.getKey())) { + return entry; + } + return new AbstractMap.SimpleEntry<>(key, finalValue); + }); + } + Migrate migrate = field.getAnnotation(Migrate.class); + if (migrate != null) { + existingMigrateNodes.add(migrate.value()); + } if (field.getType() == String.class && !(value instanceof String)) { value = value + ""; } @@ -74,25 +103,38 @@ public class Config { field.set(instance, value); return; } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to set config option: {}", key); } } } - LOGGER.error("Failed to set config option: {}: {} | {} | {}.yml", key, value, instance, root.getSimpleName()); + removedKeyVals.put(key, value); + LOGGER.warn( + "Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed or was set with an " + + "invalid value.", + key, + value, + instance, + root.getSimpleName() + ); } public boolean load(File file) { if (!file.exists()) { return false; } + existingMigrateNodes = new ArrayList<>(); YamlConfiguration yml = YamlConfiguration.loadConfiguration(file); for (String key : yml.getKeys(true)) { Object value = yml.get(key); if (value instanceof MemorySection) { continue; } - set(key, value, getClass()); + setLoadedNode(key, value, getClass()); } + for (String node : existingMigrateNodes) { + removedKeyVals.remove(node); + } + existingMigrateNodes = null; return true; } @@ -110,10 +152,10 @@ public class Config { } PrintWriter writer = new PrintWriter(file); Object instance = this; - save(writer, getClass(), instance, 0); + save(writer, getClass(), instance, 0, null); writer.close(); } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to save config file: {}", file, e); } } @@ -166,6 +208,32 @@ public class Config { } + /** + * Indicates that a field should be migrated from a node that is deleted + * + * @since 2.10.0 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Migrate { + + String value(); + + } + + /** + * Indicates that a field's default value should match another input if the config is otherwise already generated + * + * @since 2.11.0 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface CopiedFrom { + + String value(); + + } + @Ignore // This is not part of the config public static class ConfigBlock { @@ -218,11 +286,10 @@ public class Config { return value != null ? value.toString() : "null"; } - private void save(PrintWriter writer, Class clazz, final Object instance, int indent) { + private void save(PrintWriter writer, Class clazz, final Object instance, int indent, String parentNode) { try { String CTRF = System.lineSeparator(); String spacing = StringMan.repeat(" ", indent); - HashMap, Object> instances = new HashMap<>(); for (Field field : clazz.getFields()) { if (field.getAnnotation(Ignore.class) != null) { continue; @@ -239,31 +306,26 @@ public class Config { } if (current == ConfigBlock.class) { current = (Class) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0]; - comment = current.getAnnotation(Comment.class); - if (comment != null) { - for (String commentLine : comment.value()) { - writer.write(spacing + "# " + commentLine + CTRF); - } - } - BlockName blockNames = current.getAnnotation(BlockName.class); - if (blockNames != null) { - writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); - ConfigBlock configBlock = (ConfigBlock) field.get(instance); - if (configBlock == null || configBlock.getInstances().isEmpty()) { - configBlock = new ConfigBlock(); - field.set(instance, configBlock); - for (String blockName : blockNames.value()) { - configBlock.put(blockName, current.getDeclaredConstructor().newInstance()); - } - } - // Save each instance - for (Map.Entry entry : ((Map) configBlock.getRaw()).entrySet()) { - String key = entry.getKey(); - writer.write(spacing + " " + toNodeName(key) + ":" + CTRF); - save(writer, current, entry.getValue(), indent + 4); - } - } + handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current, parentNode); continue; + } else if (!removedKeyVals.isEmpty()) { + Migrate migrate = field.getAnnotation(Migrate.class); + Object value; + if (migrate != null && (value = removedKeyVals.remove(migrate.value())) != null) { + field.set(instance, value); + } + } + CopiedFrom copiedFrom; + if (copyTo != null && (copiedFrom = field.getAnnotation(CopiedFrom.class)) != null) { + String node = toNodeName(field.getName()); + node = parentNode == null ? node : parentNode + "." + node; + Map.Entry entry = copyTo.remove(node); + Object copiedVal; + if (entry == null) { + copyTo.put(node, new AbstractMap.SimpleEntry<>(copiedFrom.value(), null)); + } else if ((copiedVal = entry.getValue()) != null) { + field.set(instance, copiedVal); + } } Create create = field.getAnnotation(Create.class); if (create != null) { @@ -278,12 +340,12 @@ public class Config { writer.write(spacing + "# " + commentLine + CTRF); } } - writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); + String node = toNodeName(current.getSimpleName()); + writer.write(spacing + node + ":" + CTRF); if (value == null) { field.set(instance, value = current.getDeclaredConstructor().newInstance()); - instances.put(current, value); } - save(writer, current, value, indent + 2); + save(writer, current, value, indent + 2, parentNode == null ? node : parentNode + "." + node); } else { writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString( field.get(instance), @@ -292,7 +354,48 @@ public class Config { } } } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to save config file", e); + } + if (parentNode == null && performCopyTo) { + performCopyTo = false; + copyTo = null; + } + } + + private void handleConfigBlockSave( + PrintWriter writer, + Object instance, + int indent, + Field field, + String spacing, + String CTRF, + Class current, + String parentNode + ) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { + Comment comment = current.getAnnotation(Comment.class); + if (comment != null) { + for (String commentLine : comment.value()) { + writer.write(spacing + "# " + commentLine + CTRF); + } + } + BlockName blockNames = current.getAnnotation(BlockName.class); + if (blockNames != null) { + String node = toNodeName(current.getSimpleName()); + writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); + ConfigBlock configBlock = (ConfigBlock) field.get(instance); + if (configBlock == null || configBlock.getInstances().isEmpty()) { + configBlock = new ConfigBlock<>(); + field.set(instance, configBlock); + for (String blockName : blockNames.value()) { + configBlock.put(blockName, current.getDeclaredConstructor().newInstance()); + } + } + // Save each instance + for (Map.Entry entry : configBlock.getRaw().entrySet()) { + String key = entry.getKey(); + writer.write(spacing + " " + toNodeName(key) + ":" + CTRF); + save(writer, current, entry.getValue(), indent + 4, parentNode == null ? node : parentNode + "." + node); + } } } @@ -311,7 +414,7 @@ public class Config { return field; } catch (Throwable ignored) { LOGGER.warn( - "Invalid config field: {} for {}", + "Invalid config field: {} for {}. It is possible this is because it has been removed.", StringMan.join(split, "."), toNodeName(instance.getClass().getSimpleName()) ); @@ -379,7 +482,7 @@ public class Config { return null; } } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed retrieving instance for config node: {}", StringUtil.joinString(split, "."), e); } return null; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 174d59f37..60ec9311a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.configuration; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.limit.PropertyRemap; +import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -19,14 +20,14 @@ import java.util.stream.Stream; public class Settings extends Config { + @Ignore + static Settings INSTANCE = new Settings(); /** * @deprecated Use {@link #settings()} instead to get an instance. */ @Ignore @Deprecated(forRemoval = true, since = "2.0.0") - public static final Settings IMP = new Settings(); - @Ignore - static Settings INSTANCE = new Settings(); + public static final Settings IMP = INSTANCE; @Ignore public boolean PROTOCOL_SUPPORT_FIX = false; @Comment("These first 6 aren't configurable") // This is a comment @@ -79,6 +80,8 @@ public class Settings extends Config { @Create public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS; @Create + public GENERAL GENERAL; + @Create public ConfigBlock LIMITS; private Settings() { @@ -102,7 +105,7 @@ public class Settings extends Config { public FaweLimit getLimit(Actor actor) { FaweLimit limit; - if (actor.hasPermission("fawe.bypass") || actor.hasPermission("fawe.limit.unlimited")) { + if (actor.hasPermission("fawe.limit.unlimited")) { return FaweLimit.MAX.copy(); } limit = new FaweLimit(); @@ -120,31 +123,55 @@ public class Settings extends Config { limit.MAX_ACTIONS, newLimit.MAX_ACTIONS != -1 ? newLimit.MAX_ACTIONS : Integer.MAX_VALUE ); - limit.MAX_CHANGES = Math.max( - limit.MAX_CHANGES, + limit.MAX_CHANGES.set(Math.max( + limit.MAX_CHANGES.get(), newLimit.MAX_CHANGES != -1 ? newLimit.MAX_CHANGES : Long.MAX_VALUE - ); - limit.MAX_BLOCKSTATES = Math.max( - limit.MAX_BLOCKSTATES, + )); + limit.MAX_BLOCKSTATES.set(Math.max( + limit.MAX_BLOCKSTATES.get(), newLimit.MAX_BLOCKSTATES != -1 ? newLimit.MAX_BLOCKSTATES : Integer.MAX_VALUE - ); - limit.MAX_CHECKS = Math.max( - limit.MAX_CHECKS, + )); + limit.MAX_CHECKS.set(Math.max( + limit.MAX_CHECKS.get(), newLimit.MAX_CHECKS != -1 ? newLimit.MAX_CHECKS : Long.MAX_VALUE - ); - limit.MAX_ENTITIES = Math.max( - limit.MAX_ENTITIES, + )); + limit.MAX_ENTITIES.set(Math.max( + limit.MAX_ENTITIES.get(), newLimit.MAX_ENTITIES != -1 ? newLimit.MAX_ENTITIES : Integer.MAX_VALUE - ); - limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE); - limit.MAX_ITERATIONS = Math.max( - limit.MAX_ITERATIONS, + )); + limit.MAX_FAILS.set(Math.max( + limit.MAX_FAILS.get(), + newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE + )); + limit.MAX_ITERATIONS.set(Math.max( + limit.MAX_ITERATIONS.get(), newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE + )); + limit.MAX_RADIUS = Math.max(limit.MAX_RADIUS, newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE); + limit.MAX_SUPER_PICKAXE_SIZE = Math.max( + limit.MAX_SUPER_PICKAXE_SIZE, + newLimit.MAX_SUPER_PICKAXE_SIZE != -1 ? newLimit.MAX_SUPER_PICKAXE_SIZE : Integer.MAX_VALUE + ); + limit.MAX_BRUSH_RADIUS = Math.max( + limit.MAX_BRUSH_RADIUS, + newLimit.MAX_BRUSH_RADIUS != -1 ? newLimit.MAX_BRUSH_RADIUS : Integer.MAX_VALUE + ); + limit.MAX_BUTCHER_RADIUS = Math.max( + limit.MAX_BUTCHER_RADIUS, + newLimit.MAX_BUTCHER_RADIUS != -1 ? newLimit.MAX_BUTCHER_RADIUS : Integer.MAX_VALUE ); limit.MAX_HISTORY = Math.max( limit.MAX_HISTORY, newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE ); + limit.SCHEM_FILE_NUM_LIMIT = Math.max( + limit.SCHEM_FILE_NUM_LIMIT, + newLimit.SCHEM_FILE_NUM_LIMIT != -1 ? newLimit.SCHEM_FILE_NUM_LIMIT : Integer.MAX_VALUE + ); + limit.SCHEM_FILE_SIZE_LIMIT = Math.max( + limit.SCHEM_FILE_SIZE_LIMIT, + newLimit.SCHEM_FILE_SIZE_LIMIT != -1 ? newLimit.SCHEM_FILE_SIZE_LIMIT : Integer.MAX_VALUE + ); limit.MAX_EXPRESSION_MS = Math.max( limit.MAX_EXPRESSION_MS, newLimit.MAX_EXPRESSION_MS != -1 ? newLimit.MAX_EXPRESSION_MS : Integer.MAX_VALUE @@ -166,6 +193,7 @@ public class Settings extends Config { } } limit.UNIVERSAL_DISALLOWED_BLOCKS &= newLimit.UNIVERSAL_DISALLOWED_BLOCKS; + limit.ALLOW_LEGACY &= newLimit.ALLOW_LEGACY; if (limit.DISALLOWED_BLOCKS == null) { limit.DISALLOWED_BLOCKS = newLimit.DISALLOWED_BLOCKS.isEmpty() ? Collections.emptySet() : new HashSet<>( @@ -342,6 +370,14 @@ public class Settings extends Config { public int MAX_ITERATIONS = 1000; @Comment("Max allowed entities (e.g. cows)") public int MAX_ENTITIES = 1337; + @Comment("Max allowed radius (e.g. for //sphere)") + public int MAX_RADIUS = LocalConfiguration.MAX_RADIUS; + @Comment("Max allowed superpickaxe size") + public int MAX_SUPER_PICKAXE_SIZE = LocalConfiguration.MAX_SUPER_RADIUS; + @Comment("Max allowed brush radius") + public int MAX_BRUSH_RADIUS = LocalConfiguration.MAX_BRUSH_RADIUS; + @Comment("Max allowed butcher radius") + public int MAX_BUTCHER_RADIUS = LocalConfiguration.MAX_BUTCHER_RADIUS; @Comment({ "Blockstates include Banner, Beacon, BrewingStand, Chest, CommandBlock, ", "CreatureSpawner, Dispenser, Dropper, EndGateway, Furnace, Hopper, Jukebox, ", @@ -353,6 +389,18 @@ public class Settings extends Config { " - History on disk or memory will be deleted", }) public int MAX_HISTORY_MB = -1; + @Comment({ + "Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)", + "Set to -1 to disable" + }) + @Migrate("experimental.per-player-file-size-limit") + public int SCHEM_FILE_SIZE_LIMIT = -1; + @Comment({ + "Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)", + "Set to -1 to disable" + }) + @Migrate("experimental.per-player-file-num-limit") + public int SCHEM_FILE_NUM_LIMIT = -1; @Comment("Maximum time in milliseconds //calc can execute") public int MAX_EXPRESSION_MS = 50; @Comment({ @@ -394,12 +442,17 @@ public class Settings extends Config { " - If fast-placement is disabled, this may cause edits to be slower." }) public boolean UNIVERSAL_DISALLOWED_BLOCKS = true; + @Comment({ + "If legacy, mumerical, blocks IDs should be able to be used (i.e. 12:2)," + }) + public boolean ALLOW_LEGACY = true; @Comment({ "List of blocks to deny use of. Can be either an entire block type or a block with a specific property value.", "Where block properties are specified, any blockstate with the property will be disallowed (e.g. all directions", "of a waterlogged fence). For blocking/remapping of all occurrences of a property like waterlogged, see", "remap-properties below.", "To generate a blank list, substitute the default content with a set of square brackets [] instead.", + "The 'worldedit.anyblock' permission is not considered here.", "Example block property blocking:", " - \"minecraft:conduit[waterlogged=true]\"", " - \"minecraft:piston[extended=false,facing=west]\"", @@ -472,6 +525,9 @@ public class Settings extends Config { public int DELETE_AFTER_DAYS = 7; @Comment("Delete history in memory on logout (does not effect disk)") public boolean DELETE_ON_LOGOUT = true; + @Comment("Delete history on disk on logout") + @CopiedFrom("history.delete-on-logout") + public boolean DELETE_DISK_ON_LOGOUT = false; @Comment({ "If history should be enabled by default for plugins using WorldEdit:", " - It is faster to have disabled", @@ -510,7 +566,7 @@ public class Settings extends Config { " - A larger value will use slightly less CPU time", " - A smaller value will reduce memory usage", " - A value too small may break some operations (deform?)", - " - Values smaller than the configurated parallel-threads are not accepted", + " - Values smaller than the configured parallel-threads are not accepted", " - It is recommended this option be at least 4x greater than parallel-threads" }) @@ -543,12 +599,6 @@ public class Settings extends Config { }) public boolean POOL = true; - @Comment({ - "When using fastmode do not bother to tick existing/placed blocks/fluids", - "Only works in versions up to 1.17.1" - }) - public boolean NO_TICK_FASTMODE = true; - public static class PROGRESS { @Comment({"Display constant titles about the progress of a user's edit", @@ -574,6 +624,13 @@ public class Settings extends Config { }) public static class EXPERIMENTAL { + @Comment({ + "Undo operation batch size", + " - The size defines the number of changes read at once.", + " - Larger numbers might reduce overhead but increase latency for edits with only few changes.", + " - 0 means undo operations are not batched."}) + public int UNDO_BATCH_SIZE = 128; + @Comment({ "[UNSAFE] Directly modify the region files. (OBSOLETE - USE ANVIL COMMANDS)", " - IMPROPER USE CAN CAUSE WORLD CORRUPTION!", @@ -621,16 +678,9 @@ public class Settings extends Config { public boolean ALLOW_TICK_FLUIDS = false; @Comment({ - "Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)", - "Set to -1 to disable" + "Whether FAWE should use the incubator Vector API to accelerate some operations" }) - public int PER_PLAYER_FILE_SIZE_LIMIT = -1; - - @Comment({ - "Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)", - "Set to -1 to disable" - }) - public int PER_PLAYER_FILE_NUM_LIMIT = -1; + public boolean USE_VECTOR_API = false; } @@ -640,6 +690,13 @@ public class Settings extends Config { @Comment({"The web interface for clipboards", " - All schematics are anonymous and private", " - Downloads can be deleted by the user", " - Supports clipboard uploads, downloads and saves",}) public String URL = "https://schem.intellectualsites.com/fawe/"; + @Comment({"The url of the backend server (Arkitektonika)"}) + public String ARKITEKTONIKA_BACKEND_URL = "https://api.schematic.cloud/"; + @Comment({"The url used to generate a download link from.", "{key} will be replaced with the generated key"}) + public String ARKITEKTONIKA_DOWNLOAD_URL = "https://schematic.cloud/download/{key}"; + @Comment({"The url used to generate a deletion link from.", "{key} will be replaced with the generated key"}) + public String ARKITEKTONIKA_DELETE_URL = "https://schematic.cloud/delete/{key}"; + @Comment("The maximum amount of time in seconds the plugin can attempt to load images for.") public int MAX_IMAGE_LOAD_TIME = 5; @@ -720,6 +777,13 @@ public class Settings extends Config { " - Requires clipboard.use-disk to be enabled" }) public boolean SAVE_CLIPBOARD_NBT_TO_DISK = true; + @Comment({ + "Apply a file lock on the clipboard file (only relevant if clipboad.on-disk is enabled)", + " - Prevents other processes using the file whilst in use by FAWE", + " - This extends to other servers, useful if you have multiple servers using a unified clipboard folder", + " - May run into issues where a file lock is not correctly lifted" + }) + public boolean LOCK_CLIPBOARD_FILE = false; } @@ -742,4 +806,18 @@ public class Settings extends Config { } + public static class GENERAL { + + @Comment({ + "If the player should be relocated/unstuck when a generation command would bury them", + }) + public boolean UNSTUCK_ON_GENERATE = true; + + @Comment({ + "If unlimited limits should still require /confirm on large. Defaults to limits.default.confirm-large otherwise." + }) + public boolean LIMIT_UNLIMITED_CONFIRMS = true; + + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/file/YamlConfiguration.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/file/YamlConfiguration.java index 1e2d5b0c4..f900451b5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/file/YamlConfiguration.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/file/YamlConfiguration.java @@ -68,6 +68,7 @@ public class YamlConfiguration extends FileConfiguration { LOGGER.error("Could not read {}\n" + "Renamed to {}", file, dest.getAbsolutePath(), ex); } catch (final IOException e) { e.printStackTrace(); + ex.printStackTrace(); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/DBHandler.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/DBHandler.java index fd1263b11..755e94b2f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/DBHandler.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/DBHandler.java @@ -13,7 +13,7 @@ public class DBHandler { * @deprecated Use {@link #dbHandler()} instead. */ @Deprecated(forRemoval = true, since = "2.0.0") - public static final DBHandler IMP = new DBHandler(); + public static final DBHandler IMP = dbHandler(); private static final Logger LOGGER = LogManagerCompat.getLogger(); private static DBHandler INSTANCE; private final Map databases = new ConcurrentHashMap<>(8, 0.9f, 1); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/RollbackDatabase.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/RollbackDatabase.java index 3624e34c0..e40683f2e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/RollbackDatabase.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/database/RollbackDatabase.java @@ -64,26 +64,47 @@ public class RollbackDatabase extends AsyncNotifyQueue { public Future init() { return call(() -> { try (PreparedStatement stmt = connection.prepareStatement("CREATE TABLE IF NOT EXISTS`" + this.prefix + - "edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1`" + - "INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1`" + - "INT NOT NULL, `y2` INT NOT NULL, `size` INT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) { + "_edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1` " + + "INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1` " + + "INT NOT NULL, `y2` INT NOT NULL, `size` BIGINT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) { stmt.executeUpdate(); } - try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD COLUMN `command` VARCHAR")) { + String alterTablePrefix = "ALTER TABLE`" + this.prefix + "edits` "; + try (PreparedStatement stmt = + connection.prepareStatement(alterTablePrefix + "ADD COLUMN `command` VARCHAR")) { stmt.executeUpdate(); } catch (SQLException ignored) { } // Already updated - try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD SIZE INT DEFAULT 0 NOT NULL")) { + try (PreparedStatement stmt = + connection.prepareStatement(alterTablePrefix + "ADD COLUMN `size` BIGINT DEFAULT 0 NOT NULL")) { stmt.executeUpdate(); } catch (SQLException ignored) { } // Already updated + + boolean migrated = false; + try (PreparedStatement stmt = + connection.prepareStatement("INSERT INTO `" + this.prefix + "_edits` " + + "(player, id, time, x1, x2, z1, z2, y1, y2, size, command) " + + "SELECT player, id, time, x1, x2, z1, z2, y1, y2, size, command " + + "FROM `" + this.prefix + "edits`")) { + + stmt.executeUpdate(); + migrated = true; + } catch (SQLException ignored) { + } // Already updated + if (migrated) { + try (PreparedStatement stmt = connection.prepareStatement("DROP TABLE `" + this.prefix + "edits`")) { + stmt.executeUpdate(); + } + } return true; }); } public Future delete(UUID uuid, int id) { return call(() -> { - try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `player`=? AND `id`=?")) { + try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "_edits` WHERE `player`=? " + + "AND `id`=?")) { stmt.setBytes(1, toBytes(uuid)); stmt.setInt(2, id); return stmt.executeUpdate(); @@ -94,7 +115,7 @@ public class RollbackDatabase extends AsyncNotifyQueue { public Future getEdit(@Nonnull UUID uuid, int id) { return call(() -> { try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM`" + this.prefix + - "edits` WHERE `player`=? AND `id`=?")) { + "_edits` WHERE `player`=? AND `id`=?")) { stmt.setBytes(1, toBytes(uuid)); stmt.setInt(2, id); ResultSet result = stmt.executeQuery(); @@ -119,7 +140,7 @@ public class RollbackDatabase extends AsyncNotifyQueue { CuboidRegion region = new CuboidRegion(BlockVector3.at(x1, y1, z1), BlockVector3.at(x2, y2, z2)); long time = result.getInt("time") * 1000L; - long size = result.getInt("size"); + long size = result.getLong("size"); String command = result.getString("command"); @@ -135,7 +156,7 @@ public class RollbackDatabase extends AsyncNotifyQueue { long now = System.currentTimeMillis() / 1000; final int then = (int) (now - diff); return call(() -> { - try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `time` future = call(() -> { try { int count = 0; - String stmtStr = ascending ? uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND" + - " `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` , `id`" : - "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND" + - " `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` ASC, `id` ASC" : - uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? " + - "AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` DESC, `id` DESC" : - "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND" + - " `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC"; - try (PreparedStatement stmt = connection.prepareStatement(stmtStr)) { + String stmtStr = """ + SELECT * FROM `%s_edits` + WHERE `time` > ? + AND `x2` >= ? + AND `x1` <= ? + AND `z2` >= ? + AND `z1` <= ? + AND `y2` >= ? + AND `y1` <= ? + """; + if (uuid != null) { + stmtStr += "\n AND `player`= ?"; + } + if (ascending) { + stmtStr += "\n ORDER BY `time` ASC, `id` ASC"; + } else { + stmtStr += "\n ORDER BY `time` DESC, `id` DESC"; + } + try (PreparedStatement stmt = connection.prepareStatement(stmtStr.formatted(this.prefix))) { stmt.setInt(1, (int) (minTime / 1000)); - stmt.setInt(2, pos1.getBlockX()); - stmt.setInt(3, pos2.getBlockX()); - stmt.setInt(4, pos1.getBlockZ()); - stmt.setInt(5, pos2.getBlockZ()); + stmt.setInt(2, pos1.x()); + stmt.setInt(3, pos2.x()); + stmt.setInt(4, pos1.z()); + stmt.setInt(5, pos2.z()); // Keep 128 offset for backwards-compatibility - stmt.setInt(6, pos1.getBlockY() - 128); - stmt.setInt(7, pos2.getBlockY() - 128); + stmt.setInt(6, pos1.y() - 128); + stmt.setInt(7, pos2.y() - 128); if (uuid != null) { byte[] uuidBytes = toBytes(uuid); stmt.setBytes(8, uuidBytes); @@ -192,21 +223,22 @@ public class RollbackDatabase extends AsyncNotifyQueue { } if (delete && uuid != null) { try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + - "edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=?")) { - stmt.setInt(1, (int) (minTime / 1000)); - stmt.setInt(2, pos1.getBlockX()); - stmt.setInt(3, pos2.getBlockX()); - stmt.setInt(4, pos1.getBlockZ()); - stmt.setInt(5, pos2.getBlockZ()); - // Keep 128 offset for backwards-compatibility - stmt.setInt(6, pos1.getBlockY() - 128); - stmt.setInt(7, pos2.getBlockY() - 128); + "_edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? " + + "AND `z1`<=?")) { byte[] uuidBytes = ByteBuffer .allocate(16) .putLong(uuid.getMostSignificantBits()) .putLong(uuid.getLeastSignificantBits()) .array(); - stmt.setBytes(8, uuidBytes); + stmt.setBytes(1, uuidBytes); + stmt.setInt(2, (int) (minTime / 1000)); + stmt.setInt(3, pos1.x()); + stmt.setInt(4, pos2.x()); + stmt.setInt(5, pos1.z()); + stmt.setInt(6, pos2.z()); + // Keep 128 offset for backwards-compatibility + stmt.setInt(7, pos1.y() - 128); + stmt.setInt(8, pos2.y() - 128); } } return count; @@ -239,7 +271,7 @@ public class RollbackDatabase extends AsyncNotifyQueue { RollbackOptimizedHistory[] copy = IntStream.range(0, size) .mapToObj(i -> historyChanges.poll()).toArray(RollbackOptimizedHistory[]::new); - try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "edits`" + + try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "_edits`" + " (`player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)")) { // `player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)" for (RollbackOptimizedHistory change : copy) { @@ -252,15 +284,15 @@ public class RollbackDatabase extends AsyncNotifyQueue { BlockVector3 pos1 = change.getMinimumPoint(); BlockVector3 pos2 = change.getMaximumPoint(); - stmt.setInt(4, pos1.getX()); - stmt.setInt(5, pos2.getX()); - stmt.setInt(6, pos1.getZ()); - stmt.setInt(7, pos2.getZ()); + stmt.setInt(4, pos1.x()); + stmt.setInt(5, pos2.x()); + stmt.setInt(6, pos1.z()); + stmt.setInt(7, pos2.z()); // Keep 128 offset for backwards-compatibility - stmt.setInt(8, pos1.getY() - 128); - stmt.setInt(9, pos2.getY() - 128); + stmt.setInt(8, pos1.y() - 128); + stmt.setInt(9, pos2.y() - 128); stmt.setString(10, change.getCommand()); - stmt.setInt(11, change.size()); + stmt.setLong(11, change.longSize()); stmt.executeUpdate(); stmt.clearParameters(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java index f591cf826..325cd4191 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java @@ -3,25 +3,25 @@ package com.fastasyncworldedit.core.entity; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.entity.EntityType; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.util.function.Supplier; public class LazyBaseEntity extends BaseEntity { - private Supplier saveTag; + private Supplier saveTag; - public LazyBaseEntity(EntityType type, Supplier saveTag) { + public LazyBaseEntity(EntityType type, Supplier saveTag) { super(type); this.saveTag = saveTag; } @Nullable @Override - public CompoundBinaryTag getNbt() { - Supplier tmp = saveTag; + public LinCompoundTag getNbt() { + Supplier tmp = saveTag; if (tmp != null) { saveTag = null; if (Fawe.isMainThread()) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/BrushRadiusLimitException.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/BrushRadiusLimitException.java new file mode 100644 index 000000000..838845bd0 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/BrushRadiusLimitException.java @@ -0,0 +1,30 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.fastasyncworldedit.core.exception; + +/** + * Thrown when a maximum radius for a brush is reached. + */ +public class BrushRadiusLimitException extends RadiusLimitException { + + public BrushRadiusLimitException(int maxBrushRadius) { + super(maxBrushRadius); + } +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/OutsideWorldBoundsException.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/OutsideWorldBoundsException.java new file mode 100644 index 000000000..73d871135 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/OutsideWorldBoundsException.java @@ -0,0 +1,17 @@ +package com.fastasyncworldedit.core.exception; + +import com.sk89q.worldedit.WorldEditException; + +public class OutsideWorldBoundsException extends WorldEditException { + + private final int y; + + public OutsideWorldBoundsException(int y) { + this.y = y; + } + + public int y() { + return y; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/RadiusLimitException.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/RadiusLimitException.java new file mode 100644 index 000000000..c7f72af3a --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/exception/RadiusLimitException.java @@ -0,0 +1,41 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.fastasyncworldedit.core.exception; + +import com.sk89q.worldedit.WorldEditException; + +/** + * Thrown when a maximum radius is reached, such as, for example, + * in the case of a sphere command. + */ +public class RadiusLimitException extends WorldEditException { + + private final int maxRadius; + + public RadiusLimitException(int maxRadius) { + this.maxRadius = maxRadius; + } + + public int getMaxRadius() { + return maxRadius; + } + //FAWE end + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/TransformFactory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/TransformFactory.java index 06122c705..5cd2743ca 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/TransformFactory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/TransformFactory.java @@ -21,22 +21,17 @@ import com.sk89q.worldedit.internal.registry.AbstractFactory; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.util.formatting.text.TextComponent; -import java.util.ArrayList; import java.util.List; public class TransformFactory extends AbstractFactory { - private final RichTransformParser richTransformParser; - /** * Create a new factory. * * @param worldEdit the WorldEdit instance */ public TransformFactory(WorldEdit worldEdit) { - super(worldEdit, new NullTransformParser(worldEdit)); - - richTransformParser = new RichTransformParser(worldEdit); + super(worldEdit, new NullTransformParser(worldEdit), new RichTransformParser(worldEdit)); // split and parse each sub-transform register(new RandomTransformParser(worldEdit)); @@ -51,68 +46,7 @@ public class TransformFactory extends AbstractFactory { } @Override - public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException { - List transforms = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - ResettableExtent match = richTransformParser.parseFromInput(component, context); - if (match != null) { - transforms.add(match); - continue; - } - parseFromParsers(context, transforms, component); - } - - return getResettableExtent(input, transforms); - } - - private void parseFromParsers( - final ParserContext context, - final List transforms, - final String component - ) { - ResettableExtent match = null; - for (InputParser parser : getParsers()) { - match = parser.parseFromInput(component, context); - - if (match != null) { - break; - } - } - if (match == null) { - throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component))); - } - transforms.add(match); - } - - /** - * Parses a transform without considering parsing through the {@link RichTransformParser}, therefore not accepting - * "richer" parsing where & and , are used. Exists to prevent stack overflows. - * - * @param input input string - * @param context input context - * @return parsed result - * @throws InputParseException if no result found - */ - public ResettableExtent parseWithoutRich(String input, ParserContext context) throws InputParseException { - List transforms = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - parseFromParsers(context, transforms, component); - } - - return getResettableExtent(input, transforms); - } - - private ResettableExtent getResettableExtent(final String input, final List transforms) { + protected ResettableExtent getParsed(final String input, final List transforms) { switch (transforms.size()) { case 0: throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/FaweParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/FaweParser.java index 11d33ef67..08dd05ad1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/FaweParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/FaweParser.java @@ -37,14 +37,14 @@ public abstract class FaweParser extends InputParser implements AliasedPar for (int i = 0; i < toParse.length(); i++) { char c = toParse.charAt(i); switch (c) { - case ',', '&' -> { + case ',', '&', ' ' -> { if (expression) { continue; } String result = toParse.substring(last, i); if (!result.isEmpty()) { inputs.add(result); - and.add(c == '&'); + and.add(c == '&' || c == ' '); } else { throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", c)); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/RichParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/RichParser.java index 617143495..30dad8f37 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/RichParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/RichParser.java @@ -53,7 +53,7 @@ public abstract class RichParser extends InputParser implements AliasedPar } @Nonnull - private Function> extractArguments(String input) { + private Function> extractArguments(String input, ParserContext context) { return prefix -> { if (input.length() > prefix.length() && input.startsWith(prefix + "[")) { // input already contains argument(s) -> extract them @@ -65,7 +65,7 @@ public abstract class RichParser extends InputParser implements AliasedPar } String previous = prefix + builder; // read the suggestions for the last argument - return getSuggestions(strings[strings.length - 1], strings.length - 1) + return getSuggestions(strings[strings.length - 1], strings.length - 1, context) .map(suggestion -> previous + "[" + suggestion); } else { return Stream.of(prefix); @@ -95,7 +95,7 @@ public abstract class RichParser extends InputParser implements AliasedPar public Stream getSuggestions(String input) { return Arrays.stream(this.prefixes) .filter(validPrefix(input)) - .flatMap(extractArguments(input)); + .flatMap(extractArguments(input, new ParserContext())); } @Override @@ -122,8 +122,25 @@ public abstract class RichParser extends InputParser implements AliasedPar * @param argumentInput the already provided input for the argument at the given index. * @param index the index of the argument to get suggestions for. * @return a stream of suggestions matching the given input for the argument at the given index. + * + * @deprecated Use the version that takes a {@link ParserContext}, {@link #getSuggestions(String, int, ParserContext)} */ - protected abstract Stream getSuggestions(String argumentInput, int index); + @Deprecated + protected Stream getSuggestions(String argumentInput, int index) { + return Stream.empty(); + } + + /** + * Returns a stream of suggestions for the argument at the given index. + * + * @param argumentInput the already provided input for the argument at the given index. + * @param index the index of the argument to get suggestions for. + * @param context the context which may optionally be provided by a parser. + * @return a stream of suggestions matching the given input for the argument at the given index. + */ + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { + return getSuggestions(argumentInput, index); + } /** * Parses the already split arguments. diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/common/HotbarParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/common/HotbarParser.java new file mode 100644 index 000000000..0fe104990 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/common/HotbarParser.java @@ -0,0 +1,72 @@ +package com.fastasyncworldedit.core.extension.factory.parser.common; + +import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.extent.inventory.SlottableBlockBag; +import com.fastasyncworldedit.core.limit.FaweLimit; +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.DisallowedUsageException; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.inventory.BlockBag; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.world.block.BlockType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public abstract class HotbarParser extends SimpleInputParser { + + private final List aliases = ImmutableList.of("#hotbar"); + + protected HotbarParser(final WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return aliases; + } + + protected List getBlockTypes(ParserContext context) { + Player player = context.requirePlayer(); + BlockBag bag = player.getInventoryBlockBag(); + if (!(bag instanceof final SlottableBlockBag slottable)) { + // Matches DefaultBlockParser + throw new InputParseException(Caption.of("fawe.error.unsupported")); + } + List types = new ArrayList<>(); + FaweLimit limit = player.getLimit(); + boolean anyBlock = player.hasPermission("worldedit.anyblock"); + for (int slot = 0; slot < 9; slot++) { + BaseItem item = slottable.getItem(slot); + if (item != null && item.getType().hasBlockType()) { + BlockType type = item.getType().getBlockType(); + if (!anyBlock && worldEdit.getConfiguration().disallowedBlocks.contains(type.id().toLowerCase(Locale.ROOT))) { + throw new DisallowedUsageException(Caption.of( + "worldedit.error.disallowed-block", + TextComponent.of(type.getId()) + )); + } + if (!limit.isUnlimited()) { + if (limit.DISALLOWED_BLOCKS.contains(type.id().toLowerCase(Locale.ROOT))) { + throw new DisallowedUsageException(Caption.of( + "fawe.error.limit.disallowed-block", + TextComponent.of(type.getId()) + )); + } + } + types.add(type); + } + } + if (types.isEmpty()) { + throw new InputParseException(Caption.of("fawe.error.no-valid-on-hotbar")); + } + return types; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java index 8fbcb4ae0..7521eb10a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java @@ -19,9 +19,9 @@ public class AdjacentMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1 || index == 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java index dfd62b9b8..ea8e36665 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java @@ -22,7 +22,7 @@ public class AngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java index 954b9f53d..fd597a216 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java @@ -18,9 +18,9 @@ public class BesideMaskParser extends RichParser { } @Override - protected Stream getSuggestions(final String argumentInput, final int index) { + protected Stream getSuggestions(final String argumentInput, final int index, ParserContext context) { if (index == 0) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1 || index == 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java index a875ec802..6bab51981 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java @@ -22,7 +22,7 @@ public class ExtremaMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/HotbarMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/HotbarMaskParser.java new file mode 100644 index 000000000..4f56ae109 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/HotbarMaskParser.java @@ -0,0 +1,20 @@ +package com.fastasyncworldedit.core.extension.factory.parser.mask; + +import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.BlockTypeMask; +import com.sk89q.worldedit.function.mask.Mask; + +public class HotbarMaskParser extends HotbarParser { + + public HotbarMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) { + return new BlockTypeMask(context.getExtent(), getBlockTypes(context)); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java index dff4e8f32..00a285b95 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java @@ -22,7 +22,7 @@ public class ROCAngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java index 8a57c73af..559b3bab3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java @@ -18,7 +18,7 @@ public class RadiusMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichMaskParser.java index 4e0fbfa91..4086d5d3d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichMaskParser.java @@ -4,7 +4,7 @@ import com.fastasyncworldedit.core.command.SuggestInputParseException; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.FaweParser; import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder; -import com.fastasyncworldedit.core.function.mask.MaskUnion; +import com.sk89q.worldedit.function.mask.MaskUnion; import com.fastasyncworldedit.core.util.StringMan; import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.worldedit.WorldEdit; @@ -97,11 +97,11 @@ public class RichMaskParser extends FaweParser { )), () -> { if (full.length() == 1) { - return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("")); + return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context)); } return new ArrayList<>(worldEdit .getMaskFactory() - .getSuggestions(command.toLowerCase(Locale.ROOT))); + .getSuggestions(command.toLowerCase(Locale.ROOT), context)); } ); } @@ -143,7 +143,7 @@ public class RichMaskParser extends FaweParser { int end = command.lastIndexOf(']'); mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context); } else { - BlockMaskBuilder builder = new BlockMaskBuilder(); + BlockMaskBuilder builder = new BlockMaskBuilder(context); try { builder.addRegex(full); } catch (InputParseException ignored) { @@ -164,11 +164,11 @@ public class RichMaskParser extends FaweParser { )), () -> { if (full.length() == 1) { - return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("")); + return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context)); } return new ArrayList<>(worldEdit .getMaskFactory() - .getSuggestions(command.toLowerCase(Locale.ROOT))); + .getSuggestions(command.toLowerCase(Locale.ROOT), context)); } ); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java index f6a21ef6f..47b56cb56 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java @@ -24,12 +24,12 @@ public class RichOffsetMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } if (index == 3) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java index 4674057b2..f1d2e6c55 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java @@ -20,7 +20,7 @@ public class SimplexMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java index ab011f412..7a85e708b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java @@ -23,7 +23,7 @@ public class SurfaceAngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index <= 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java index 7074fdb13..d471435e6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java @@ -25,7 +25,7 @@ public class AngleColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index != 0) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java index 35d28382d..1fd2e8b2f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java @@ -25,7 +25,7 @@ public class AverageColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 4) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java index 0adbe2cd7..74e1b5b65 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java @@ -54,7 +54,7 @@ public class BiomePatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return BiomeType.REGISTRY.getSuggestions(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java index 246e024c6..4ae760918 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java @@ -26,9 +26,9 @@ public class BufferedPattern2DParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java index 49fd27495..3660aa902 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java @@ -26,9 +26,9 @@ public class BufferedPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java index 9b424d5eb..0363b2ec5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java @@ -26,7 +26,7 @@ public class ColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 4) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java index 2218f479e..d5ace9036 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java @@ -25,7 +25,7 @@ public class DesaturatePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/HotbarPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/HotbarPatternParser.java new file mode 100644 index 000000000..2f1db622e --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/HotbarPatternParser.java @@ -0,0 +1,26 @@ +package com.fastasyncworldedit.core.extension.factory.parser.pattern; + +import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser; +import com.fastasyncworldedit.core.math.random.TrueRandom; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.pattern.RandomPattern; +import com.sk89q.worldedit.world.block.BlockType; + +public class HotbarPatternParser extends HotbarParser { + + public HotbarPatternParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public Pattern parseFromSimpleInput(String input, ParserContext context) { + RandomPattern random = new RandomPattern(new TrueRandom()); + for (BlockType type : getBlockTypes(context)) { + random.add(type, 1); + } + return random; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java index 5a310f60a..3e77a6ef1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java @@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.RichParser; -import com.fastasyncworldedit.core.function.pattern.Linear2DBlockPattern; +import com.fastasyncworldedit.core.math.random.Linear2DRandom; import com.google.common.base.Preconditions; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.SuggestionHelper; @@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nonnull; -import java.util.Set; import java.util.stream.Stream; public class Linear2DPatternParser extends RichParser { @@ -29,9 +28,9 @@ public class Linear2DPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; @@ -59,9 +58,8 @@ public class Linear2DPatternParser extends RichParser { zScale = Integer.parseInt(arguments[2]); Preconditions.checkArgument(zScale != 0); } - if (inner instanceof RandomPattern) { - Set patterns = ((RandomPattern) inner).getPatterns(); - return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale); + if (inner instanceof RandomPattern rp) { + return new RandomPattern(new Linear2DRandom(xScale, zScale), rp); } throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() + " cannot be used with " + getPrefix())); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java index ef45e8faa..7f7ffd7aa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java @@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.RichParser; -import com.fastasyncworldedit.core.function.pattern.Linear3DBlockPattern; +import com.fastasyncworldedit.core.math.random.Linear3DRandom; import com.google.common.base.Preconditions; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.SuggestionHelper; @@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nonnull; -import java.util.Set; import java.util.stream.Stream; public class Linear3DPatternParser extends RichParser { @@ -29,9 +28,9 @@ public class Linear3DPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; @@ -64,9 +63,8 @@ public class Linear3DPatternParser extends RichParser { zScale = Integer.parseInt(arguments[3]); Preconditions.checkArgument(zScale != 0); } - if (inner instanceof RandomPattern) { - Set patterns = ((RandomPattern) inner).getPatterns(); - return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale, zScale); + if (inner instanceof RandomPattern rp) { + return new RandomPattern(new Linear3DRandom(xScale, yScale, zScale), rp); } throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() + " cannot be used with " + getPrefix())); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java index 785e8261d..e0d5d3105 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java @@ -28,9 +28,9 @@ public class LinearPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java index 3aed039c3..92fcd6f5f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java @@ -25,10 +25,10 @@ public class MaskedPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); - case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); + case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); default -> Stream.empty(); }; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java index 8e3ac729f..915963d4c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java @@ -24,9 +24,9 @@ public class NoXPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java index 2cc00c8ad..34e3724a4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java @@ -24,9 +24,9 @@ public class NoYPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java index 927d13d0c..aaa9cf5fd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java @@ -24,9 +24,9 @@ public class NoZPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java index 37ad97417..d91a66f44 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java @@ -36,12 +36,12 @@ public abstract class NoisePatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } if (index == 1) { - return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java index 6ae72c7a0..ff203208c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java @@ -25,9 +25,9 @@ public class OffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java index 2af68adc8..587d8d81f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.RichParser; import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder; import com.fastasyncworldedit.core.function.pattern.RandomFullClipboardPattern; +import com.google.common.base.Function; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.input.InputParseException; @@ -33,7 +34,7 @@ public class RandomFullClipboardPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { switch (index) { case 0: if (argumentInput.equals("#") || argumentInput.equals("#c")) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java index 2486ef119..6d910b0eb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class RandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java index bf56c1ddb..43c4d0fbf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java @@ -24,9 +24,9 @@ public class RelativePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java index bb40f029d..e93521529 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java @@ -25,7 +25,7 @@ public class SaturatePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 3) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java index 618c463d6..ebc6b74b5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class SolidRandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java index aa28b11d8..31a7060d5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class SurfaceRandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java index 5bf33d3a0..1c4d25b91 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java @@ -28,7 +28,7 @@ public class TypeSwapPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 2) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java index 01d4868d3..ef72110c4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java @@ -23,9 +23,9 @@ public class Linear3DTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java index 026f38338..fb646b56b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java @@ -23,9 +23,9 @@ public class LinearTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java index 471359b78..3aeebfd45 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java @@ -26,11 +26,11 @@ public class OffsetTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java index cf81db4ce..6405fa5ec 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java @@ -24,11 +24,11 @@ public class PatternTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java index 19ae8a599..c7f756efd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java @@ -25,12 +25,12 @@ public class RotateTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java index 4bab68d0f..028c79f05 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java @@ -24,11 +24,11 @@ public class ScaleTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java index 2f71407b2..b2ad0acbd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java @@ -24,11 +24,11 @@ public class SpreadTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ConsumeBindings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ConsumeBindings.java index c1997bb0d..615f1a586 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ConsumeBindings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ConsumeBindings.java @@ -200,6 +200,7 @@ public class ConsumeBindings extends Bindings { public BaseBlock baseBlock(Actor actor, String argument) { ParserContext parserContext = new ParserContext(); parserContext.setActor(actor); + parserContext.setTryLegacy(actor.getLimit().ALLOW_LEGACY); if (actor instanceof Entity) { Extent extent = ((Entity) actor).getExtent(); if (extent instanceof World) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java new file mode 100644 index 000000000..1fd588ec4 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java @@ -0,0 +1,7 @@ +package com.fastasyncworldedit.core.extension.platform.binding; + +import com.sk89q.worldedit.EditSession; + +public record EditSessionHolder(EditSession session) { + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java index bc1e2bfbf..9ac01d9c3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java @@ -3,7 +3,11 @@ package com.fastasyncworldedit.core.extension.platform.binding; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.database.DBHandler; import com.fastasyncworldedit.core.database.RollbackDatabase; +import com.fastasyncworldedit.core.extent.LimitExtent; +import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder; +import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.regions.FaweMaskManager; +import com.fastasyncworldedit.core.util.ExtentTraverser; import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.image.ImageUtil; import com.sk89q.worldedit.EditSession; @@ -11,6 +15,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.util.annotation.AllowedRegion; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.platform.Actor; @@ -25,6 +30,7 @@ import org.enginehub.piston.inject.Key; import org.enginehub.piston.util.ValueProvider; import java.awt.image.BufferedImage; +import java.lang.reflect.Method; import java.net.URI; import java.util.Optional; @@ -52,11 +58,33 @@ public class ProvideBindings extends Bindings { @Binding public EditSession editSession(LocalSession localSession, Actor actor, InjectedValueAccess context) { + Method commandMethod = + context.injectedValue(Key.of(InjectedValueStore.class)).get().injectedValue(Key.of(Method.class)).get(); + Arguments arguments = context.injectedValue(Key.of(Arguments.class)).orElse(null); String command = arguments == null ? null : arguments.get(); - EditSession editSession = localSession.createEditSession(actor, command); - editSession.enableStandardMode(); - Request.request().setEditSession(editSession); + boolean synchronousSetting = commandMethod.getAnnotation(SynchronousSettingExpected.class) != null; + EditSessionHolder holder = context.injectedValue(Key.of(EditSessionHolder.class)).orElse(null); + EditSession editSession = holder != null ? holder.session() : null; + if (editSession == null) { + editSession = localSession.createEditSession(actor, command); + editSession.enableStandardMode(); + } else { + LimitExtent limitExtent = new ExtentTraverser<>(editSession).findAndGet(LimitExtent.class); + if (limitExtent != null) { + limitExtent.setProcessing(!synchronousSetting); + if (!synchronousSetting) { + ExtentBatchProcessorHolder processorHolder = new ExtentTraverser<>(editSession).findAndGet( + ExtentBatchProcessorHolder.class); + if (processorHolder != null) { + processorHolder.addProcessor(limitExtent); + } else { + throw new FaweException(Caption.of("fawe.error.no-process-non-synchronous-edit")); + } + } + } + Request.request().setEditSession(editSession); + } return editSession; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java index d7b8a986e..7f84be430 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java @@ -24,7 +24,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - return getExtent().setBlock(location.getX() + dx, location.getY() + dy, location.getZ() + dz, block); + return getExtent().setBlock(location.x() + dx, location.y() + dy, location.z() + dz, block); } @Override @@ -49,7 +49,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent { @Override public BlockState getBlock(BlockVector3 location) { - return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + return getBlock(location.x(), location.y(), location.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java index f1c523ce3..11f15131f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java @@ -101,7 +101,7 @@ public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IB @SuppressWarnings("unchecked") private > B checkBlock(B block) { if (blockedBlocks != null) { - if (blockedBlocks.contains(block.getBlockType().getId())) { + if (blockedBlocks.contains(block.getBlockType().id())) { return (B) (block instanceof BlockState ? RESERVED : RESERVED.toBaseBlock()); // set to reserved/empty } } @@ -140,7 +140,7 @@ public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IB } BlockState state = BlockTypesCache.states[block]; if (blockedBlocks != null) { - if (blockedBlocks.contains(state.getBlockType().getId())) { + if (blockedBlocks.contains(state.getBlockType().id())) { blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; continue; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/FaweRegionExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/FaweRegionExtent.java index 84044f9b2..4f4cce126 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/FaweRegionExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/FaweRegionExtent.java @@ -64,11 +64,11 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc @Override public final boolean contains(BlockVector3 p) { - return contains(p.getBlockX(), p.getBlockY(), p.getBlockZ()); + return contains(p.x(), p.y(), p.z()); } public final boolean contains(BlockVector2 p) { - return contains(p.getBlockX(), p.getBlockZ()); + return contains(p.x(), p.z()); } @Override @@ -96,12 +96,12 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc @Override public BiomeType getBiome(BlockVector3 position) { - return getBiomeType(position.getX(), position.getY(), position.getZ()); + return getBiomeType(position.x(), position.y(), position.z()); } @Override public BiomeType getBiomeType(int x, int y, int z) { - if (!contains(x, z)) { + if (!contains(x, y, z)) { if (!limit.MAX_FAILS()) { WEManager.weManager().cancelEditSafe(this, FaweCache.OUTSIDE_REGION); } @@ -112,7 +112,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc @Override public BaseBlock getFullBlock(BlockVector3 position) { - return getFullBlock(position.getX(), position.getY(), position.getZ()); + return getFullBlock(position.x(), position.y(), position.z()); } @Override @@ -128,7 +128,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc @Override public BlockState getBlock(BlockVector3 position) { - return getBlock(position.getX(), position.getY(), position.getZ()); + return getBlock(position.x(), position.y(), position.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java index ff57e00da..c22d9e6be 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java @@ -6,12 +6,11 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.regions.RegionWrapper; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import java.util.Collection; import java.util.Collections; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; public class HeightBoundExtent extends FaweRegionExtent { @@ -50,7 +49,8 @@ public class HeightBoundExtent extends FaweRegionExtent { @Override public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { - if (trimY(set, min, max, true) | trimNBT(set, this::contains)) { + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + if (trimY(set, min, max, true) | trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)))) { return set; } return null; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java index 2fc5133c6..720b5e57b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -66,7 +67,7 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { - return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); + return setBlock(location.x(), location.y(), location.z(), block); } @Nullable @@ -74,7 +75,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public Entity createEntity(Location location, BaseEntity state) { final Entity entity = super.createEntity(location, state); if (state != null) { - this.changeSet.addEntityCreate(state.getNbtData()); + this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt())); } return entity; } @@ -84,7 +85,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public Entity createEntity(Location location, BaseEntity state, UUID uuid) { final Entity entity = super.createEntity(location, state, uuid); if (state != null) { - this.changeSet.addEntityCreate(state.getNbtData()); + this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt())); } return entity; } @@ -110,8 +111,8 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public boolean setBiome(BlockVector3 position, BiomeType newBiome) { BiomeType oldBiome = this.getBiome(position); - if (!oldBiome.getId().equals(newBiome.getId())) { - this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockY(), position.getBlockZ(), oldBiome, newBiome); + if (!oldBiome.id().equals(newBiome.id())) { + this.changeSet.addBiomeChange(position.x(), position.y(), position.z(), oldBiome, newBiome); return getExtent().setBiome(position, newBiome); } else { return false; @@ -121,7 +122,7 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public boolean setBiome(int x, int y, int z, BiomeType newBiome) { BiomeType oldBiome = this.getBiome(mutable.setComponents(x, y, z)); - if (!oldBiome.getId().equals(newBiome.getId())) { + if (!oldBiome.id().equals(newBiome.id())) { this.changeSet.addBiomeChange(x, y, z, oldBiome, newBiome); return getExtent().setBiome(x, y, z, newBiome); } else { @@ -154,11 +155,10 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public boolean remove() { - final Location location = this.entity.getLocation(); final BaseEntity state = this.entity.getState(); final boolean success = this.entity.remove(); if (state != null && success) { - HistoryExtent.this.changeSet.addEntityRemove(state.getNbtData()); + HistoryExtent.this.changeSet.addEntityRemove(FaweCompoundTag.of(state.getNbt())); } return success; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java index 24d440c57..90ca09810 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java @@ -1,11 +1,15 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.extent.filter.block.ExtentFilterBlock; -import com.fastasyncworldedit.core.function.generator.GenBase; -import com.fastasyncworldedit.core.function.generator.Resource; +import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.queue.Filter; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.util.ExtentTraverser; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -17,7 +21,6 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.text.Component; @@ -37,18 +40,22 @@ import java.util.Set; import java.util.UUID; import java.util.function.Consumer; -public class LimitExtent extends AbstractDelegateExtent { +public class LimitExtent extends AbstractDelegateExtent implements IBatchProcessor { private final FaweLimit limit; private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; private final Consumer onErrorMessage; + private final int chunk_size; + private boolean processing; /** * Create a new instance. * * @param extent the extent * @param limit the limit + * @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)} */ + @Deprecated(forRemoval = true, since = "2.12.0") public LimitExtent(Extent extent, FaweLimit limit) { this(extent, limit, c -> { }); @@ -60,11 +67,33 @@ public class LimitExtent extends AbstractDelegateExtent { * @param extent the extent * @param limit the limit * @param onErrorMessage consumer to handle a component generated by exceptions + * @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)} */ + @Deprecated(forRemoval = true, since = "2.12.0") public LimitExtent(Extent extent, FaweLimit limit, Consumer onErrorMessage) { + this(extent, limit, onErrorMessage, false); + } + + /** + * Create a new instance. + * + * @param extent the extent + * @param limit the limit + * @param onErrorMessage consumer to handle a component generated by exceptions + * @param processing if this limit extent is expected to be processing + * @since 2.12.0 + */ + public LimitExtent( + Extent extent, + FaweLimit limit, + Consumer onErrorMessage, + boolean processing + ) { super(extent); this.limit = limit; this.onErrorMessage = onErrorMessage; + this.chunk_size = 16 * 16 * (extent.getMaxY() - extent.getMinY()); + this.processing = processing; } private void handleException(FaweException e) { @@ -81,7 +110,7 @@ public class LimitExtent extends AbstractDelegateExtent { public List getEntities(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); try { - return super.getEntities(region); + return extent.getEntities(region); } catch (FaweException e) { handleException(e); return Collections.emptyList(); @@ -92,7 +121,7 @@ public class LimitExtent extends AbstractDelegateExtent { public List getEntities() { limit.THROW_MAX_CHECKS(); try { - return super.getEntities(); + return extent.getEntities(); } catch (FaweException e) { handleException(e); return Collections.emptyList(); @@ -105,7 +134,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - return super.createEntity(location, entity); + return extent.createEntity(location, entity); } catch (FaweException e) { handleException(e); return null; @@ -118,7 +147,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - return super.createEntity(location, entity, uuid); + return extent.createEntity(location, entity, uuid); } catch (FaweException e) { handleException(e); return null; @@ -130,7 +159,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - super.removeEntity(x, y, z, uuid); + extent.removeEntity(x, y, z, uuid); } catch (FaweException e) { handleException(e); } @@ -138,9 +167,9 @@ public class LimitExtent extends AbstractDelegateExtent { @Override public boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) { - limit.THROW_MAX_CHANGES(Character.MAX_VALUE); + limit.THROW_MAX_CHANGES(chunk_size); try { - return super.regenerateChunk(x, z, type, seed); + return extent.regenerateChunk(x, z, type, seed); } catch (FaweException e) { handleException(e); return false; @@ -151,7 +180,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getHighestTerrainBlock(int x, int z, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getHighestTerrainBlock(x, z, minY, maxY); + return extent.getHighestTerrainBlock(x, z, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -162,7 +191,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getHighestTerrainBlock(x, z, minY, maxY, filter); + return extent.getHighestTerrainBlock(x, z, minY, maxY, filter); } catch (FaweException e) { handleException(e); return minY; @@ -173,7 +202,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceLayer(x, z, y, minY, maxY); + return extent.getNearestSurfaceLayer(x, z, y, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -184,7 +213,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); } catch (FaweException e) { handleException(e); return minY; @@ -195,7 +224,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -206,7 +235,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); } catch (FaweException e) { handleException(e); return minY; @@ -217,7 +246,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); } catch (FaweException e) { handleException(e); return minY; @@ -237,91 +266,47 @@ public class LimitExtent extends AbstractDelegateExtent { ) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); } catch (FaweException e) { handleException(e); return minY; } } - @Override - public void addCaves(Region region) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addCaves(region); - } - - @Override - public void generate(Region region, GenBase gen) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.generate(region, gen); - } - - @Override - public void addSchems(Region region, Mask mask, List clipboards, int rarity, boolean rotate) throws - WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addSchems(region, mask, clipboards, rarity, rotate); - } - - @Override - public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.spawnResource(region, gen, rarity, frequency); - } - - @Override - public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws - WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addOre(region, mask, material, size, frequency, rarity, minY, maxY); - } - - @Override - public void addOres(Region region, Mask mask) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addOres(region, mask); - } - @Override public List> getBlockDistribution(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.getBlockDistribution(region); + return extent.getBlockDistribution(region); } @Override public List> getBlockDistributionWithData(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.getBlockDistributionWithData(region); + return extent.getBlockDistributionWithData(region); } @Override public int countBlocks(Region region, Set searchBlocks) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.countBlocks(region, searchBlocks); + return extent.countBlocks(region, searchBlocks); } @Override public int countBlocks(Region region, Mask searchMask) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.countBlocks(region, searchMask); + return extent.countBlocks(region, searchMask); } @Override public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { limit.THROW_MAX_CHANGES(region.getVolume()); - return super.setBlocks(region, block); + return extent.setBlocks(region, block); } @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHANGES(region.getVolume()); - return super.setBlocks(region, pattern); + return extent.setBlocks(region, pattern); } @Override @@ -329,41 +314,34 @@ public class LimitExtent extends AbstractDelegateExtent { MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, filter, replacement); + return extent.replaceBlocks(region, filter, replacement); } @Override public int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, filter, pattern); + return extent.replaceBlocks(region, filter, pattern); } @Override public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, mask, pattern); - } - - @Override - public int center(Region region, Pattern pattern) throws MaxChangedBlocksException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - return super.center(region, pattern); + return extent.replaceBlocks(region, mask, pattern); } @Override public int setBlocks(Set vset, Pattern pattern) { limit.THROW_MAX_CHANGES(vset.size()); - return super.setBlocks(vset, pattern); + return extent.setBlocks(vset, pattern); } @Override public T apply(Region region, T filter, boolean full) { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.apply(region, filter, full); + return extent.apply(region, filter, full); } @Override @@ -373,12 +351,12 @@ public class LimitExtent extends AbstractDelegateExtent { size = ((Collection) positions).size(); } else if (positions instanceof Region) { BlockVector3 dim = ((Region) positions).getDimensions(); - size = dim.getX() * dim.getY() * dim.getZ(); + size = dim.x() * dim.y() * dim.z(); } else if (positions instanceof Extent) { BlockVector3 min = ((Extent) positions).getMinimumPoint(); BlockVector3 max = ((Extent) positions).getMinimumPoint(); BlockVector3 dim = max.subtract(min).add(BlockVector3.ONE); - size = dim.getX() * dim.getY() * dim.getZ(); + size = dim.x() * dim.y() * dim.z(); } else { ExtentFilterBlock block = new ExtentFilterBlock(this); for (BlockVector3 pos : positions) { @@ -393,14 +371,14 @@ public class LimitExtent extends AbstractDelegateExtent { } limit.THROW_MAX_CHECKS(size); limit.THROW_MAX_CHANGES(size); - return super.apply(positions, filter); + return extent.apply(positions, filter); } @Override public BlockState getBlock(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getBlock(position); + return extent.getBlock(position); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState(); @@ -411,7 +389,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BlockState getBlock(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getBlock(x, y, z); + return extent.getBlock(x, y, z); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState(); @@ -422,7 +400,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BaseBlock getFullBlock(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getFullBlock(position); + return extent.getFullBlock(position); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState().toBaseBlock(); @@ -433,7 +411,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BaseBlock getFullBlock(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getFullBlock(x, y, z); + return extent.getFullBlock(x, y, z); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState().toBaseBlock(); @@ -444,7 +422,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BiomeType getBiome(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getBiome(position); + return extent.getBiome(position); } catch (FaweException e) { handleException(e); return BiomeTypes.FOREST; @@ -455,7 +433,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BiomeType getBiomeType(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getBiomeType(x, y, z); + return extent.getBiomeType(x, y, z); } catch (FaweException e) { handleException(e); return BiomeTypes.FOREST; @@ -470,7 +448,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_BLOCKSTATES(); } try { - return super.setBlock(position, block); + return extent.setBlock(position, block); } catch (FaweException e) { handleException(e); return false; @@ -484,7 +462,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_BLOCKSTATES(); } try { - return super.setBlock(x, y, z, block); + return extent.setBlock(x, y, z, block); } catch (FaweException e) { handleException(e); return false; @@ -494,9 +472,9 @@ public class LimitExtent extends AbstractDelegateExtent { @Override public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { limit.THROW_MAX_CHANGES(); - limit.MAX_BLOCKSTATES(); + limit.THROW_MAX_BLOCKSTATES(); try { - return super.setTile(x, y, z, tile); + return extent.setTile(x, y, z, tile); } catch (FaweException e) { handleException(e); return false; @@ -507,7 +485,7 @@ public class LimitExtent extends AbstractDelegateExtent { public boolean setBiome(BlockVector3 position, BiomeType biome) { limit.THROW_MAX_CHANGES(); try { - return super.setBiome(position, biome); + return extent.setBiome(position, biome); } catch (FaweException e) { handleException(e); return false; @@ -518,11 +496,41 @@ public class LimitExtent extends AbstractDelegateExtent { public boolean setBiome(int x, int y, int z, BiomeType biome) { limit.THROW_MAX_CHANGES(); try { - return super.setBiome(x, y, z, biome); + return extent.setBiome(x, y, z, biome); } catch (FaweException e) { handleException(e); return false; } } + public void setProcessing(boolean processing) { + this.processing = processing; + } + + @Override + public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { + if (!processing) { + return set; + } + int tiles = set.tiles().size(); + int ents = set.entities().size() + set.getEntityRemoves().size(); + limit.THROW_MAX_CHANGES(tiles + ents); + limit.THROW_MAX_BLOCKSTATES(tiles); + limit.THROW_MAX_ENTITIES(ents); + return set; + } + + @Override + public Extent construct(final Extent child) { + if (extent != child) { + new ExtentTraverser(this).setNext(child); + } + return this; + } + + @Override + public ProcessorScope getScope() { + return ProcessorScope.READING_SET_BLOCKS; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java index 6d74acc16..d5e8e57e8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java @@ -38,9 +38,9 @@ public class PositionTransformExtent extends ResettableExtent { if (min == null) { min = pos; } - mutable.mutX(pos.getX() - min.getX()); - mutable.mutY(pos.getY() - min.getY()); - mutable.mutZ(pos.getZ() - min.getZ()); + mutable.mutX(pos.x() - min.x()); + mutable.mutY(pos.y() - min.y()); + mutable.mutZ(pos.z() - min.z()); MutableVector3 tmp = new MutableVector3(transform.apply(mutable.toVector3())); return min.add(tmp.roundHalfUp().toBlockPoint()); } @@ -49,9 +49,9 @@ public class PositionTransformExtent extends ResettableExtent { if (min == null) { min = BlockVector3.at(x, y, z); } - mutable.mutX(x - min.getX()); - mutable.mutY(y - min.getY()); - mutable.mutZ(z - min.getZ()); + mutable.mutX(x - min.x()); + mutable.mutY(y - min.y()); + mutable.mutZ(z - min.z()); MutableVector3 tmp = new MutableVector3(transform.apply(mutable.toVector3())); return min.add(tmp.roundHalfUp().toBlockPoint()); } @@ -73,10 +73,10 @@ public class PositionTransformExtent extends ResettableExtent { @Override public BiomeType getBiome(BlockVector3 position) { - mutable.mutX(position.getBlockX()); - mutable.mutZ(position.getBlockZ()); - mutable.mutY(position.getBlockY()); - return super.getBiome(getPos(mutable.getX(), mutable.getY(), mutable.getZ())); + mutable.mutX(position.x()); + mutable.mutZ(position.z()); + mutable.mutY(position.y()); + return super.getBiome(getPos(mutable.x(), mutable.y(), mutable.z())); } @Override @@ -92,10 +92,10 @@ public class PositionTransformExtent extends ResettableExtent { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - mutable.mutX(position.getBlockX()); - mutable.mutZ(position.getBlockZ()); - mutable.mutY(position.getBlockY()); - return super.setBiome(getPos(mutable.getX(), mutable.getY(), mutable.getZ()), biome); + mutable.mutX(position.x()); + mutable.mutZ(position.z()); + mutable.mutY(position.y()); + return super.setBiome(getPos(mutable.x(), mutable.y(), mutable.z()), biome); } public void setTransform(Transform transform) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java index 5abe90348..e08e1535f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java @@ -80,12 +80,12 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { - return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); + return setBlock(location.x(), location.y(), location.z(), block); } @Override public BlockState getBlock(BlockVector3 location) { - return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + return getBlock(location.x(), location.y(), location.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java index 6c2230372..6da0a2ac6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java @@ -41,8 +41,8 @@ public class SourceMaskExtent extends TemporalExtent { @Override public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - set(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); - return mask.test(location) && super.setBlock(location.getX(), location.getY(), location.getZ(), block); + set(location.x(), location.y(), location.z(), block); + return mask.test(location) && super.setBlock(location.x(), location.y(), location.z(), block); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java index ded96d5aa..6939743d7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java @@ -2,14 +2,12 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.util.ExtentTraverser; -import com.google.common.collect.ImmutableMap; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -20,18 +18,17 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; -import java.util.HashMap; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor { @@ -77,79 +74,82 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc if (!(block instanceof BaseBlock localBlock)) { return block; } - if (!localBlock.hasNbtData()) { + final LinCompoundTag nbt = localBlock.getNbt(); + if (nbt == null) { return block; } - CompoundTag nbt = localBlock.getNbtData(); - Map value = new HashMap<>(nbt.getValue()); + LinCompoundTag.Builder nbtBuilder = nbt.toBuilder(); for (String key : strip) { - value.remove(key); + nbtBuilder.remove(key); } - return (B) localBlock.toBaseBlock(new CompoundTag(value)); + return (B) localBlock.toBaseBlock(nbtBuilder.build()); } public T stripEntityNBT(T entity) { - if (!entity.hasNbtData()) { + LinCompoundTag nbt = entity.getNbt(); + if (nbt == null) { return entity; } - CompoundTag nbt = entity.getNbtData(); - Map value = new HashMap<>(nbt.getValue()); + LinCompoundTag.Builder nbtBuilder = nbt.toBuilder(); for (String key : strip) { - value.remove(key); + nbtBuilder.remove(key); } - entity.setNbtData(new CompoundTag(value)); + entity.setNbt(nbtBuilder.build()); return entity; } @Override public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - Map tiles = set.getTiles(); - Set entities = set.getEntities(); + Map tiles = set.tiles(); + Collection entities = set.entities(); if (tiles.isEmpty() && entities.isEmpty()) { return set; } boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap; - for (final Map.Entry entry : tiles.entrySet()) { - ImmutableMap.Builder map = ImmutableMap.builder(); - final AtomicBoolean isStripped = new AtomicBoolean(false); - entry.getValue().getValue().forEach((k, v) -> { - if (strip.contains(k.toLowerCase())) { - isStripped.set(true); - } else { - map.put(k, v); - } - }); - if (isStripped.get()) { + for (final var entry : tiles.entrySet()) { + FaweCompoundTag original = entry.getValue(); + FaweCompoundTag result = stripNbt(original); + if (original != result) { if (isBv3ChunkMap) { // Replace existing value with stripped value - tiles.put(entry.getKey(), new CompoundTag(map.build())); + tiles.put(entry.getKey(), result); } else { - entry.setValue(new CompoundTag(map.build())); + entry.setValue(result); } } } - Set stripped = new HashSet<>(); - Iterator iterator = entities.iterator(); + Set stripped = new HashSet<>(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - CompoundTag entity = iterator.next(); - ImmutableMap.Builder map = ImmutableMap.builder(); - final AtomicBoolean isStripped = new AtomicBoolean(false); - entity.getValue().forEach((k, v) -> { - if (strip.contains(k.toUpperCase(Locale.ROOT))) { - isStripped.set(true); - } else { - map.put(k, v); - } - }); - if (isStripped.get()) { + FaweCompoundTag original = iterator.next(); + FaweCompoundTag result = stripNbt(original); + if (original != result) { iterator.remove(); - stripped.add(new CompoundTag(map.build())); + stripped.add(result); } } - set.getEntities().addAll(stripped); + // this relies on entities.addAll(...) not throwing an exception if empty+unmodifiable (=> stripped is empty too) + entities.addAll(stripped); return set; } + private FaweCompoundTag stripNbt( + FaweCompoundTag compoundTag + ) { + LinCompoundTag.Builder builder = LinCompoundTag.builder(); + boolean stripped = false; + for (var entry : compoundTag.linTag().value().entrySet()) { + String k = entry.getKey(); + LinTag v = entry.getValue(); + if (strip.contains(k.toLowerCase(Locale.ROOT))) { + stripped = true; + } else { + builder.put(k, v); + } + } + return stripped ? FaweCompoundTag.of(builder.build()) : compoundTag; + } + @Nullable @Override public Extent construct(final Extent child) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java index ac36bef5a..ff0fa5106 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java @@ -44,7 +44,7 @@ public class TemporalExtent extends PassthroughExtent { @Override public BlockState getBlock(BlockVector3 position) { - if (position.getX() == x && position.getY() == y && position.getZ() == z) { + if (position.x() == x && position.y() == y && position.z() == z) { return block.toImmutableState(); } return super.getBlock(position); @@ -60,7 +60,7 @@ public class TemporalExtent extends PassthroughExtent { @Override public BaseBlock getFullBlock(BlockVector3 position) { - if (position.getX() == x && position.getY() == y && position.getZ() == z) { + if (position.x() == x && position.y() == y && position.z() == z) { if (block instanceof BaseBlock) { return (BaseBlock) block; } else { @@ -72,7 +72,7 @@ public class TemporalExtent extends PassthroughExtent { @Override public BiomeType getBiome(BlockVector3 position) { - if (position.getX() == bx && position.getZ() == bz) { + if (position.x() == bx && position.z() == bz) { return biome; } return super.getBiome(position); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java index 91b99b025..daa731d3c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java @@ -12,6 +12,10 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +/** + * @deprecated Unused internal, will be removed in v3 + */ +@Deprecated(forRemoval = true, since = "2.9.2") public class TransformExtent extends BlockTransformExtent { private final MutableVector3 mutable1 = new MutableVector3(); @@ -51,13 +55,13 @@ public class TransformExtent extends BlockTransformExtent { if (min == null) { min = pos; } - mutable1.mutX(pos.getX() - min.getX()); - mutable1.mutY(pos.getY() - min.getY()); - mutable1.mutZ(pos.getZ() - min.getZ()); + mutable1.mutX(pos.x() - min.x()); + mutable1.mutY(pos.y() - min.y()); + mutable1.mutZ(pos.z() - min.z()); Vector3 tmp = getTransform().apply(mutable1); - mutable2.mutX(tmp.getX() + min.getX()); - mutable2.mutY(tmp.getY() + min.getY()); - mutable2.mutZ(tmp.getZ() + min.getZ()); + mutable2.mutX(tmp.x() + min.x()); + mutable2.mutY(tmp.y() + min.y()); + mutable2.mutZ(tmp.z() + min.z()); return mutable2; } @@ -65,20 +69,20 @@ public class TransformExtent extends BlockTransformExtent { if (min == null) { min = BlockVector3.at(x, y, z); } - mutable1.mutX(x - min.getX()); - mutable1.mutY(y - min.getY()); - mutable1.mutZ(z - min.getZ()); + mutable1.mutX(x - min.x()); + mutable1.mutY(y - min.y()); + mutable1.mutZ(z - min.z()); Vector3 tmp = getTransform().apply(mutable1); - mutable2.mutX(tmp.getX() + min.getX()); - mutable2.mutY(tmp.getY() + min.getY()); - mutable2.mutZ(tmp.getZ() + min.getZ()); + mutable2.mutX(tmp.x() + min.x()); + mutable2.mutY(tmp.y() + min.y()); + mutable2.mutZ(tmp.z() + min.z()); return tmp.toBlockPoint(); } @Override public BlockState getBlock(int x, int y, int z) { BlockVector3 p = getPos(x, y, z); - return transform(super.getBlock(p.getX(), p.getY(), p.getZ())); + return transform(super.getBlock(p.x(), p.y(), p.z())); } @Override @@ -89,7 +93,7 @@ public class TransformExtent extends BlockTransformExtent { @Override public BiomeType getBiomeType(int x, int y, int z) { BlockVector3 p = getPos(x, y, z); - return super.getBiomeType(p.getX(), y, p.getZ()); + return super.getBiomeType(p.x(), p.y(), p.z()); } @Override @@ -110,7 +114,7 @@ public class TransformExtent extends BlockTransformExtent { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { BlockVector3 p = getPos(x, y, z); - return super.setBiome(p.getX(), p.getY(), p.getZ(), biome); + return super.setBiome(p.x(), p.y(), p.z(), biome); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java index 1a30a0df8..ef7cc0461 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java @@ -2,9 +2,11 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -41,7 +43,7 @@ public class CPUOptimizedClipboard extends LinearClipboard { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override @@ -92,7 +94,7 @@ public class CPUOptimizedClipboard extends LinearClipboard { @Override public BiomeType getBiome(BlockVector3 position) { - return getBiome(getBiomeIndex(position.getX(), position.getY(), position.getZ())); + return getBiome(getBiomeIndex(position.x(), position.y(), position.z())); } public void convertTilesToIndex() { @@ -152,7 +154,7 @@ public class CPUOptimizedClipboard extends LinearClipboard { public Collection getTileEntities() { convertTilesToIndex(); nbtMapIndex.replaceAll((index, tag) -> { - Map values = new HashMap<>(tag.getValue()); + Map> values = new HashMap<>(tag.getValue()); if (!values.containsKey("x")) { int y = index / getArea(); index -= y * getArea(); @@ -175,8 +177,14 @@ public class CPUOptimizedClipboard extends LinearClipboard { return true; } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + // TODO replace + return setTile(x, y, z, new CompoundTag(tile.linTag())); + } + private boolean setTile(int index, CompoundTag tag) { - final Map values = new HashMap<>(tag.getValue()); + final Map> values = new HashMap<>(tag.getValue()); values.remove("x"); values.remove("y"); values.remove("z"); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java index 60290fe9c..163651cfb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java @@ -6,15 +6,18 @@ import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismat import com.fastasyncworldedit.core.internal.io.ByteBufferInputStream; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.ReflectionUtils; +import com.google.common.collect.Collections2; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.internal.util.LogManagerCompat; @@ -28,6 +31,8 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTagType; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -64,7 +69,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { private static final int VERSION_2_HEADER_SIZE = 27; // Header size of "version 2" i.e. when NBT/entities could be saved private static final Map LOCK_HOLDER_CACHE = new ConcurrentHashMap<>(); - private final HashMap nbtMap; + private final HashMap nbtMap; private final File file; private final int headerSize; @@ -257,12 +262,12 @@ public class DiskOptimizedClipboard extends LinearClipboard { try (NBTInputStream nbtIS = new NBTInputStream(MainUtil.getCompressedIS(new ByteBufferInputStream(tmp)))) { Iterator iter = nbtIS.toIterator(); while (nbtCount > 0 && iter.hasNext()) { // TileEntities are stored "before" entities - CompoundTag tag = iter.next(); - int x = tag.getInt("x"); - int y = tag.getInt("y"); - int z = tag.getInt("z"); + LinCompoundTag tag = iter.next().toLinTag(); + int x = tag.getTag("x", LinTagType.intTag()).valueAsInt(); + int y = tag.getTag("y", LinTagType.intTag()).valueAsInt(); + int z = tag.getTag("z", LinTagType.intTag()).valueAsInt(); IntTriple pos = new IntTriple(x, y, z); - nbtMap.put(pos, tag); + nbtMap.put(pos, FaweCompoundTag.of(tag)); nbtCount--; } while (entitiesCount > 0 && iter.hasNext()) { @@ -314,22 +319,24 @@ public class DiskOptimizedClipboard extends LinearClipboard { private void init() throws IOException { if (this.fileChannel == null) { this.fileChannel = braf.getChannel(); - try { - FileLock lock = this.fileChannel.lock(); - LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock)); - } catch (OverlappingFileLockException e) { - LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName()); - if (existing != null) { - long ms = System.currentTimeMillis() - existing.lockHeldSince; - LOGGER.error( - "Cannot lock clipboard file {} acquired by thread {}, {}ms ago", - file.getName(), - existing.thread, - ms - ); + if (Settings.settings().CLIPBOARD.LOCK_CLIPBOARD_FILE) { + try { + FileLock lock = this.fileChannel.lock(); + LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock)); + } catch (OverlappingFileLockException e) { + LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName()); + if (existing != null) { + long ms = System.currentTimeMillis() - existing.lockHeldSince; + LOGGER.error( + "Cannot lock clipboard file {} acquired by thread {}, {}ms ago", + file.getName(), + existing.thread, + ms + ); + } + // Rethrow to prevent clipboard access + throw e; } - // Rethrow to prevent clipboard access - throw e; } this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length()); } @@ -366,7 +373,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override @@ -424,7 +431,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { @Override public BiomeType getBiome(BlockVector3 position) { - return getBiome(getBiomeIndex(position.getX(), position.getY(), position.getZ())); + return getBiome(getBiomeIndex(position.x(), position.y(), position.z())); } public BlockArrayClipboard toClipboard() { @@ -445,9 +452,9 @@ public class DiskOptimizedClipboard extends LinearClipboard { super.setOrigin(origin); origin = origin.subtract(offset); try { - byteBuffer.putShort(10, (short) origin.getBlockX()); - byteBuffer.putShort(12, (short) origin.getBlockY()); - byteBuffer.putShort(14, (short) origin.getBlockZ()); + byteBuffer.putShort(10, (short) origin.x()); + byteBuffer.putShort(12, (short) origin.y()); + byteBuffer.putShort(14, (short) origin.z()); } catch (Throwable e) { e.printStackTrace(); } @@ -457,9 +464,9 @@ public class DiskOptimizedClipboard extends LinearClipboard { protected void setOffset(BlockVector3 offset) { super.setOffset(offset); try { - byteBuffer.putShort(16, (short) offset.getBlockX()); - byteBuffer.putShort(18, (short) offset.getBlockY()); - byteBuffer.putShort(20, (short) offset.getBlockZ()); + byteBuffer.putShort(16, (short) offset.x()); + byteBuffer.putShort(18, (short) offset.y()); + byteBuffer.putShort(20, (short) offset.z()); } catch (Throwable e) { e.printStackTrace(); } @@ -566,8 +573,8 @@ public class DiskOptimizedClipboard extends LinearClipboard { ))) { if (!nbtMap.isEmpty()) { try { - for (CompoundTag tag : nbtMap.values()) { - nbtOS.writeTag(tag); + for (FaweCompoundTag tag : nbtMap.values()) { + nbtOS.writeTag(new CompoundTag(tag.linTag())); } } catch (IOException e) { e.printStackTrace(); @@ -593,11 +600,11 @@ public class DiskOptimizedClipboard extends LinearClipboard { for (BlockArrayClipboard.ClipboardEntity entity : entities) { if (entity.getState() != null && entity.getState().getNbtData() != null) { CompoundTag data = entity.getState().getNbtData(); - HashMap value = new HashMap<>(data.getValue()); + HashMap> value = new HashMap<>(data.getValue()); List pos = new ArrayList<>(3); - pos.add(new DoubleTag(entity.getLocation().getX())); - pos.add(new DoubleTag(entity.getLocation().getX())); - pos.add(new DoubleTag(entity.getLocation().getX())); + pos.add(new DoubleTag(entity.getLocation().x())); + pos.add(new DoubleTag(entity.getLocation().x())); + pos.add(new DoubleTag(entity.getLocation().x())); value.put("Pos", new ListTag(DoubleTag.class, pos)); nbtOS.writeTag(new CompoundTag(value)); } @@ -645,7 +652,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { @Override public Collection getTileEntities() { - return nbtMap.values(); + return Collections2.transform(nbtMap.values(), fct -> new CompoundTag(fct.linTag())); } public int getIndex(int x, int y, int z) { @@ -663,10 +670,10 @@ public class DiskOptimizedClipboard extends LinearClipboard { private BaseBlock toBaseBlock(BlockState state, int i) { if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) { - CompoundTag nbt; + FaweCompoundTag nbt; if (nbtMap.size() < 4) { nbt = null; - for (Map.Entry entry : nbtMap.entrySet()) { + for (Map.Entry entry : nbtMap.entrySet()) { IntTriple key = entry.getKey(); int index = getIndex(key.x(), key.y(), key.z()); if (index == i) { @@ -681,15 +688,15 @@ public class DiskOptimizedClipboard extends LinearClipboard { int x = newI - z * getWidth(); nbt = nbtMap.get(new IntTriple(x, y, z)); } - return state.toBaseBlock(nbt); + return state.toBaseBlock(nbt == null ? null : nbt.linTag()); } return state.toBaseBlock(); } private BaseBlock toBaseBlock(BlockState state, int x, int y, int z) { if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) { - CompoundTag nbt = nbtMap.get(new IntTriple(x, y, z)); - return state.toBaseBlock(nbt); + FaweCompoundTag nbt = nbtMap.get(new IntTriple(x, y, z)); + return state.toBaseBlock(nbt == null ? null : nbt.linTag()); } return state.toBaseBlock(); } @@ -716,12 +723,8 @@ public class DiskOptimizedClipboard extends LinearClipboard { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - final Map values = new HashMap<>(tag.getValue()); - values.put("x", new IntTag(x)); - values.put("y", new IntTag(y)); - values.put("z", new IntTag(z)); - nbtMap.put(new IntTriple(x, y, z), new CompoundTag(values)); + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + nbtMap.put(new IntTriple(x, y, z), NbtUtils.withPosition(tile, x, y, z)); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java index 8e18c2c19..983ea79b0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java @@ -1,7 +1,7 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -84,7 +84,8 @@ public final class EmptyClipboard implements Clipboard { return false; } - public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tile) throws WorldEditException { + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java index 143168504..7d60f3ee4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java @@ -57,6 +57,10 @@ public abstract class LinearClipboard extends SimpleClipboard { */ public abstract void streamBiomes(IntValueReader task); + /** + * @deprecated will be removed as it is unused and uses outdated types + */ + @Deprecated(forRemoval = true, since = "2.12.0") public abstract Collection getTileEntities(); @Override @@ -106,7 +110,7 @@ public abstract class LinearClipboard extends SimpleClipboard { @Nullable @Override public Entity createEntity(Location location, BaseEntity entity, UUID uuid) { - Map map = new HashMap<>(entity.getNbtData().getValue()); + Map> map = new HashMap<>(entity.getNbtData().getValue()); NBTUtils.addUUIDToMap(map, uuid); entity.setNbtData(new CompoundTag(map)); BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java index 449795e5d..c113c720c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java @@ -3,10 +3,12 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -64,7 +66,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override @@ -115,7 +117,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard { @Override public BiomeType getBiome(BlockVector3 position) { - return getBiome(getBiomeIndex(position.getX(), position.getY(), position.getZ())); + return getBiome(getBiomeIndex(position.x(), position.y(), position.z())); } private int getOrdinal(int index) { @@ -254,7 +256,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard { @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { - final Map values = new HashMap<>(tag.getValue()); + final Map> values = new HashMap<>(tag.getValue()); values.put("x", new IntTag(x)); values.put("y", new IntTag(y)); values.put("z", new IntTag(z)); @@ -262,6 +264,12 @@ public class MemoryOptimizedClipboard extends LinearClipboard { return true; } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + // TODO replace + return setTile(x, y, z, new CompoundTag(tile.linTag())); + } + @Override public > boolean setBlock(int x, int y, int z, B block) { return setBlock(getIndex(x, y, z), block); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java index 4f7245d27..aa608be05 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java @@ -1,14 +1,11 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.Fawe; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.Tag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.request.Request; @@ -18,9 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nullable; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.function.Supplier; @@ -77,6 +72,16 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard { }; } + @Override + public BlockVector3 getMinimumPoint() { + return region.getMinimumPoint(); + } + + @Override + public BlockVector3 getMaximumPoint() { + return region.getMaximumPoint(); + } + @Override public Region getRegion() { return region; @@ -101,7 +106,7 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { + public boolean tile(int x, int y, int z, FaweCompoundTag tag) { throw new UnsupportedOperationException("Clipboard is immutable"); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java index 05089a111..4efa4f456 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java @@ -58,6 +58,9 @@ public class ResizableClipboardBuilder extends MemoryOptimizedHistory { } public Clipboard build() { + if (longSize() == 0) { + return EmptyClipboard.getInstance(); + } BlockVector3 pos1 = BlockVector3.at(minX, minY, minZ); BlockVector3 pos2 = BlockVector3.at(maxX, maxY, maxZ); CuboidRegion region = new CuboidRegion(pos1, pos2); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java index c01abd787..f902f6007 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/SimpleClipboard.java @@ -70,17 +70,17 @@ public abstract class SimpleClipboard implements Clipboard { @Override public final int getWidth() { - return size.getBlockX(); + return size.x(); } @Override public final int getHeight() { - return size.getBlockY(); + return size.y(); } @Override public final int getLength() { - return size.getBlockZ(); + return size.z(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/WorldCopyClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/WorldCopyClipboard.java index cdd4ae8df..4bb50ca73 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/WorldCopyClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/WorldCopyClipboard.java @@ -56,7 +56,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { @Override public BiomeType getBiome(BlockVector3 position) { - return getExtent().getBiomeType(position.getX(), position.getY(), position.getZ()); + return getExtent().getBiomeType(position.x(), position.y(), position.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReader.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV2.java similarity index 95% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReader.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV2.java index d884e0151..4c71a9f66 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReader.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV2.java @@ -9,7 +9,7 @@ import com.fastasyncworldedit.core.internal.io.FaweInputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; import com.fastasyncworldedit.core.jnbt.streamer.StreamDelegate; import com.fastasyncworldedit.core.jnbt.streamer.ValueReader; -import com.sk89q.jnbt.AdventureNBTConverter; +import com.sk89q.jnbt.LinBusConverter; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.NBTInputStream; @@ -53,7 +53,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Reads schematic files using the Sponge Schematic Specification. */ -public class FastSchematicReader extends NBTSchematicReader { +public class FastSchematicReaderV2 extends NBTSchematicReader { private static final Logger LOGGER = LogManagerCompat.getLogger(); private final NBTInputStream inputStream; @@ -88,7 +88,7 @@ public class FastSchematicReader extends NBTSchematicReader { * * @param inputStream the input stream to read from */ - public FastSchematicReader(NBTInputStream inputStream) { + public FastSchematicReaderV2(NBTInputStream inputStream) { checkNotNull(inputStream); this.inputStream = inputStream; this.fixer = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataFixer(); @@ -109,26 +109,22 @@ public class FastSchematicReader extends NBTSchematicReader { if (fixer == null || dataVersion == -1) { return tag; } - //FAWE start - BinaryTag - return (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( + return (CompoundTag) LinBusConverter.fromLinBus(fixer.fixUp( DataFixer.FixTypes.BLOCK_ENTITY, - tag.asBinaryTag(), + tag.toLinTag(), dataVersion )); - //FAWE end } private CompoundTag fixEntity(CompoundTag tag) { if (fixer == null || dataVersion == -1) { return tag; } - //FAWE start - BinaryTag - return (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( + return (CompoundTag) LinBusConverter.fromLinBus(fixer.fixUp( DataFixer.FixTypes.ENTITY, - tag.asBinaryTag(), + tag.toLinTag(), dataVersion )); - //FAWE end } private String fixBiome(String biomePalettePart) { @@ -251,7 +247,7 @@ public class FastSchematicReader extends NBTSchematicReader { throw new IOException("This schematic version is not supported; Version: " + version + ", DataVersion: " + dataVersion + ". It's very likely your schematic has an invalid file extension," + " if the schematic has been created on a version lower than 1.13.2, the extension MUST be `.schematic`," + - " elsewise the schematic can't be read properly."); + " elsewise the schematic can't be read properly. If you are using a litematica schematic, it is not supported!"); } if (blocks != null) { @@ -344,7 +340,7 @@ public class FastSchematicReader extends NBTSchematicReader { y = pos[1]; z = pos[2]; } - Map values = new HashMap<>(tile.getValue()); + Map> values = new HashMap<>(tile.getValue()); Tag id = values.get("Id"); if (id != null) { values.put("x", new IntTag(x)); @@ -371,7 +367,7 @@ public class FastSchematicReader extends NBTSchematicReader { // entities if (entities != null && !entities.isEmpty()) { for (Map entRaw : entities) { - Map value = new HashMap<>(FaweCache.INSTANCE.asTag(entRaw).getValue()); + Map> value = new HashMap<>(FaweCache.INSTANCE.asTag(entRaw).getValue()); StringTag id = (StringTag) value.get("Id"); if (id == null) { id = (StringTag) value.get("id"); @@ -396,8 +392,8 @@ public class FastSchematicReader extends NBTSchematicReader { int locY = loc.getBlockY(); int locZ = loc.getBlockZ(); BlockVector3 max = min.add(dimensions).subtract(BlockVector3.ONE); - if (locX < min.getX() || locY < min.getY() || locZ < min.getZ() - || locX > max.getX() || locY > max.getY() || locZ > max.getZ()) { + if (locX < min.x() || locY < min.y() || locZ < min.z() + || locX > max.x() || locY > max.y() || locZ > max.z()) { for (Entity e : clipboard.getEntities()) { clipboard.removeEntity(e); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java new file mode 100644 index 000000000..0e48f32d0 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java @@ -0,0 +1,839 @@ +package com.fastasyncworldedit.core.extent.clipboard.io; + +import com.fastasyncworldedit.core.extent.clipboard.LinearClipboard; +import com.fastasyncworldedit.core.extent.clipboard.SimpleClipboard; +import com.fastasyncworldedit.core.internal.io.ResettableFileInputStream; +import com.fastasyncworldedit.core.internal.io.VarIntStreamIterator; +import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.IOUtil; +import com.fastasyncworldedit.core.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.NBTConstants; +import com.sk89q.jnbt.NBTInputStream; +import com.sk89q.jnbt.NBTOutputStream; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.extent.clipboard.io.sponge.ReaderUtil; +import com.sk89q.worldedit.extent.clipboard.io.sponge.VersionedDataFixer; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.DataFixer; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import com.sk89q.worldedit.world.entity.EntityType; +import it.unimi.dsi.fastutil.io.FastBufferedInputStream; +import it.unimi.dsi.fastutil.io.FastBufferedOutputStream; +import net.jpountz.lz4.LZ4BlockInputStream; +import net.jpountz.lz4.LZ4BlockOutputStream; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinTagType; +import org.jetbrains.annotations.ApiStatus; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.Set; +import java.util.UUID; +import java.util.function.BooleanSupplier; +import java.util.function.Function; +import java.util.zip.GZIPInputStream; + +/** + * ClipboardReader for the Sponge Schematic Format v3. + * Not necessarily much faster than {@link com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader}, but uses a + * stream based approach to keep the memory overhead minimal (especially in larger schematics) + * + * @since 2.11.1 + */ +@SuppressWarnings("removal") // JNBT +public class FastSchematicReaderV3 implements ClipboardReader { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static final byte CACHE_IDENTIFIER_END = 0x00; + private static final byte CACHE_IDENTIFIER_BLOCK = 0x01; + private static final byte CACHE_IDENTIFIER_BIOMES = 0x02; + private static final byte CACHE_IDENTIFIER_ENTITIES = 0x03; + private static final byte CACHE_IDENTIFIER_BLOCK_TILE_ENTITIES = 0x04; + + private final InputStream parentStream; + private final MutableBlockVector3 dimensions = MutableBlockVector3.at(0, 0, 0); + private final Set remainingTags; + + private DataInputStream dataInputStream; + private NBTInputStream nbtInputStream; + + private VersionedDataFixer dataFixer; + private BlockVector3 offset; + private BlockVector3 origin = BlockVector3.ZERO; + private BlockState[] blockPalette; + private BiomeType[] biomePalette; + private int dataVersion = -1; + + // Only used if the InputStream is not file based (and therefor does not support resets based on FileChannels) + // and the file is unordered + // Data and Palette cache is separated, as the data requires a fully populated palette - and the order is not guaranteed + private byte[] dataCache; + private byte[] paletteCache; + private OutputStream dataCacheWriter; + private OutputStream paletteCacheWriter; + + + public FastSchematicReaderV3(@NonNull InputStream stream) { + Objects.requireNonNull(stream, "stream"); + if (stream instanceof ResettableFileInputStream) { + stream.mark(Integer.MAX_VALUE); + this.remainingTags = new HashSet<>(); + } else if (stream instanceof FileInputStream fileInputStream) { + stream = new ResettableFileInputStream(fileInputStream); + stream.mark(Integer.MAX_VALUE); + this.remainingTags = new HashSet<>(); + } else if (stream instanceof FastBufferedInputStream || stream instanceof BufferedInputStream) { + this.remainingTags = null; + } else { + stream = new FastBufferedInputStream(stream); + this.remainingTags = null; + } + this.parentStream = stream; + } + + @Override + public Clipboard read(final UUID uuid, final Function createOutput) throws IOException { + Clipboard clipboard = null; + + this.setSubStreams(); + skipHeader(this.dataInputStream); + + byte type; + String tag; + while ((type = dataInputStream.readByte()) != NBTConstants.TYPE_END) { + tag = this.dataInputStream.readUTF(); + switch (tag) { + case "DataVersion" -> { + final Platform platform = + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + this.dataVersion = this.dataInputStream.readInt(); + this.dataFixer = ReaderUtil.getVersionedDataFixer(this.dataVersion, platform, platform.getDataVersion()); + } + case "Metadata" -> { + LinCompoundTag metadataCompoundTag = + (LinCompoundTag) this.nbtInputStream.readTagPayload(NBTConstants.TYPE_COMPOUND, 0).toLinTag(); + + LinCompoundTag worldEditTag = metadataCompoundTag.findTag("WorldEdit", LinTagType.compoundTag()); + if (worldEditTag != null) { // allowed to be optional + LinIntArrayTag originTag = worldEditTag.findTag("Origin", LinTagType.intArrayTag()); + if (originTag != null) { // allowed to be optional + int[] parts = originTag.value(); + + if (parts.length != 3) { + throw new IOException("`Metadata > WorldEdit > Origin` int array length is invalid."); + } + + this.origin = BlockVector3.at(parts[0], parts[1], parts[2]); + } + } + } + case "Offset" -> { + this.dataInputStream.skipNBytes(4); // Array Length field (4 byte int) + this.offset = BlockVector3.at( + this.dataInputStream.readInt(), + this.dataInputStream.readInt(), + this.dataInputStream.readInt() + ); + } + case "Width" -> this.dimensions.mutX(this.dataInputStream.readShort() & 0xFFFF); + case "Height" -> this.dimensions.mutY(this.dataInputStream.readShort() & 0xFFFF); + case "Length" -> this.dimensions.mutZ(this.dataInputStream.readShort() & 0xFFFF); + case "Blocks" -> readBlocks(clipboard); + case "Biomes" -> readBiomes(clipboard); + case "Entities" -> readEntities(clipboard); + default -> this.nbtInputStream.readTagPayloadLazy(type, 0); + } + if (clipboard == null && this.areDimensionsAvailable()) { + clipboard = createOutput.apply(this.dimensions); + } + } + + if (clipboard == null) { + throw new IOException("Invalid schematic - missing dimensions"); + } + if (dataFixer == null) { + throw new IOException("Invalid schematic - missing DataVersion"); + } + + if (this.supportsReset() && !remainingTags.isEmpty()) { + readRemainingDataReset(clipboard); + } else if (this.dataCacheWriter != null || this.paletteCacheWriter != null) { + readRemainingDataCache(clipboard); + } + + clipboard.setOrigin(this.offset.multiply(-1)); + if (clipboard instanceof SimpleClipboard simpleClipboard && !this.offset.equals(BlockVector3.ZERO)) { + clipboard = new BlockArrayClipboard(simpleClipboard, this.offset.add(this.origin)); + } + return clipboard; + } + + + /** + * Reads all locally cached data (due to reset not being available) and applies them to the clipboard. + *

+ * Firstly, closes all cache writers (which adds the END identifier to each and fills the cache byte arrays on this instance) + * If required, creates all missing palettes first (as needed by all remaining data). + * At last writes all missing data (block states, tile entities, biomes, entities). + * + * @param clipboard The clipboard to write into. + * @throws IOException on I/O error. + */ + private void readRemainingDataCache(Clipboard clipboard) throws IOException { + byte identifier; + if (this.paletteCacheWriter != null) { + this.paletteCacheWriter.close(); + } + if (this.dataCacheWriter != null) { + this.dataCacheWriter.close(); + } + if (this.paletteCache != null) { + try (final DataInputStream cacheStream = new DataInputStream(new FastBufferedInputStream( + new LZ4BlockInputStream(new FastBufferedInputStream(new ByteArrayInputStream(this.paletteCache)))))) { + while ((identifier = cacheStream.readByte()) != CACHE_IDENTIFIER_END) { + if (identifier == CACHE_IDENTIFIER_BLOCK) { + this.readPaletteMap(cacheStream, this.provideBlockPaletteInitializer()); + continue; + } + if (identifier == CACHE_IDENTIFIER_BIOMES) { + this.readPaletteMap(cacheStream, this.provideBiomePaletteInitializer()); + continue; + } + throw new IOException("invalid cache state - got identifier: 0x" + identifier); + } + } + } + try (final DataInputStream cacheStream = new DataInputStream(new FastBufferedInputStream( + new LZ4BlockInputStream(new FastBufferedInputStream(new ByteArrayInputStream(this.dataCache))))); + final NBTInputStream cacheNbtIn = new NBTInputStream(cacheStream)) { + while ((identifier = cacheStream.readByte()) != CACHE_IDENTIFIER_END) { + switch (identifier) { + case CACHE_IDENTIFIER_BLOCK -> this.readPaletteData(cacheStream, this.getBlockWriter(clipboard)); + case CACHE_IDENTIFIER_BIOMES -> this.readPaletteData(cacheStream, this.getBiomeWriter(clipboard)); + case CACHE_IDENTIFIER_ENTITIES -> { + cacheStream.skipNBytes(1); // list child type (TAG_Compound) + this.readEntityContainers( + cacheStream, + cacheNbtIn, + DataFixer.FixTypes.ENTITY, + this.provideEntityTransformer(clipboard) + ); + } + case CACHE_IDENTIFIER_BLOCK_TILE_ENTITIES -> { + cacheStream.skipNBytes(1); // list child type (TAG_Compound) + this.readEntityContainers( + cacheStream, + cacheNbtIn, + DataFixer.FixTypes.BLOCK_ENTITY, + this.provideTileEntityTransformer(clipboard) + ); + } + default -> throw new IOException("invalid cache state - got identifier: 0x" + identifier); + } + } + } + } + + /** + * Reset the main stream of this clipboard and reads all remaining data that could not be read or fixed yet. + * Might need two iterations if the DataVersion tag is after the Blocks tag while the Palette inside the Blocks tag is not + * at the first position. + * + * @param clipboard The clipboard to write into. + * @throws IOException on I/O error. + */ + private void readRemainingDataReset(Clipboard clipboard) throws IOException { + byte type; + String tag; + outer: + while (!this.remainingTags.isEmpty()) { + this.reset(); + skipHeader(this.dataInputStream); + while ((type = dataInputStream.readByte()) != NBTConstants.TYPE_END) { + tag = dataInputStream.readUTF(); + byte b = tag.equals("Blocks") ? CACHE_IDENTIFIER_BLOCK : + tag.equals("Biomes") ? CACHE_IDENTIFIER_BIOMES : + tag.equals("Entities") ? CACHE_IDENTIFIER_ENTITIES : + CACHE_IDENTIFIER_END; + if (!this.remainingTags.remove(b)) { + this.nbtInputStream.readTagPayloadLazy(type, 0); + continue; + } + switch (tag) { + case "Blocks" -> readBlocks(clipboard); + case "Biomes" -> readBiomes(clipboard); + case "Entities" -> readEntities(clipboard); + default -> this.nbtInputStream.readTagPayloadLazy(type, 0); // Should never happen, but just in case + } + if (this.remainingTags.isEmpty()) { + break outer; + } + } + } + } + + /** + * {@inheritDoc} + *

+ * Requires {@link #read()}, {@link #read(UUID)} or {@link #read(UUID, Function)} to be called before. + */ + @Override + public OptionalInt getDataVersion() { + return this.dataVersion > -1 ? OptionalInt.of(this.dataVersion) : OptionalInt.empty(); + } + + private void readBlocks(Clipboard target) throws IOException { + this.blockPalette = new BlockState[BlockTypesCache.states.length]; + readPalette( + target != null, + CACHE_IDENTIFIER_BLOCK, + () -> this.blockPalette[0] != null, + this.provideBlockPaletteInitializer(), + this.getBlockWriter(target), + (type, tag) -> { + if (!tag.equals("BlockEntities")) { + try { + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_LIST, 0); + } catch (IOException e) { + LOGGER.error("Failed to skip additional tag", e); + } + return; + } + try { + this.readTileEntities(target); + } catch (IOException e) { + LOGGER.warn("Failed to read tile entities", e); + } + } + ); + } + + private void readBiomes(Clipboard target) throws IOException { + this.biomePalette = new BiomeType[BiomeType.REGISTRY.size()]; + readPalette( + target != null, + CACHE_IDENTIFIER_BIOMES, + () -> this.biomePalette[0] != null, + this.provideBiomePaletteInitializer(), + this.getBiomeWriter(target), + (type, tag) -> { + try { + this.nbtInputStream.readTagPayloadLazy(type, 0); + } catch (IOException e) { + LOGGER.error("Failed to skip additional tag in biome container: {}", tag, e); + } + } + ); + } + + private void readEntities(@Nullable Clipboard target) throws IOException { + if (target == null || this.dataFixer == null) { + if (supportsReset()) { + this.remainingTags.add(CACHE_IDENTIFIER_ENTITIES); + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_LIST, 0); + return; + } + // Easier than streaming for now + final NBTOutputStream cacheStream = new NBTOutputStream(this.getDataCacheWriter()); + cacheStream.writeByte(CACHE_IDENTIFIER_ENTITIES); + cacheStream.writeTagPayload(this.nbtInputStream.readTagPayload(NBTConstants.TYPE_LIST, 0)); + return; + } + if (this.dataInputStream.read() != NBTConstants.TYPE_COMPOUND) { + throw new IOException("Expected a compound block for entity"); + } + this.readEntityContainers( + this.dataInputStream, this.nbtInputStream, DataFixer.FixTypes.ENTITY, this.provideEntityTransformer(target) + ); + } + + private void readTileEntities(Clipboard target) throws IOException { + if (target == null || this.dataFixer == null) { + if (supportsReset()) { + this.remainingTags.add(CACHE_IDENTIFIER_BLOCK); // use block identifier, as this method will be called by + // readBlocks again + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_LIST, 0); + return; + } + // Easier than streaming for now + final NBTOutputStream cacheStream = new NBTOutputStream(this.getDataCacheWriter()); + cacheStream.writeByte(CACHE_IDENTIFIER_BLOCK_TILE_ENTITIES); + cacheStream.writeTagPayload(this.nbtInputStream.readTagPayload(NBTConstants.TYPE_LIST, 0)); + return; + } + if (this.dataInputStream.read() != NBTConstants.TYPE_COMPOUND) { + throw new IOException("Expected a compound block for tile entity"); + } + this.readEntityContainers( + this.dataInputStream, + this.nbtInputStream, + DataFixer.FixTypes.BLOCK_ENTITY, + this.provideTileEntityTransformer(target) + ); + } + + private void readEntityContainers( + DataInputStream stream, + NBTInputStream nbtStream, + DataFixer.FixType fixType, + EntityTransformer transformer + ) throws IOException { + double x, y, z; + LinCompoundTag tag; + String id; + byte type; + int count = stream.readInt(); + while (count-- > 0) { + x = -1; + y = -1; + z = -1; + tag = null; + id = null; + while ((type = stream.readByte()) != NBTConstants.TYPE_END) { + switch (type) { + // Depending on the type of entity container (tile vs "normal") the pos consists of either doubles or ints + case NBTConstants.TYPE_INT_ARRAY -> { + if (!stream.readUTF().equals("Pos")) { + throw new IOException("Expected INT_ARRAY tag to be Pos"); + } + stream.skipNBytes(4); // count of following ints - for pos = 3 + x = stream.readInt(); + y = stream.readInt(); + z = stream.readInt(); + } + case NBTConstants.TYPE_LIST -> { + if (!stream.readUTF().equals("Pos")) { + throw new IOException("Expected LIST tag to be Pos"); + } + if (stream.readByte() != NBTConstants.TYPE_DOUBLE) { + throw new IOException("Expected LIST Pos tag to contain DOUBLE"); + } + stream.skipNBytes(4); // count of following doubles - for pos = 3 + x = stream.readDouble(); + y = stream.readDouble(); + z = stream.readDouble(); + } + case NBTConstants.TYPE_STRING -> { + if (!stream.readUTF().equals("Id")) { + throw new IOException("Expected STRING tag to be Id"); + } + id = stream.readUTF(); + } + case NBTConstants.TYPE_COMPOUND -> { + if (!stream.readUTF().equals("Data")) { + throw new IOException("Expected COMPOUND tag to be Data"); + } + if (!(nbtStream.readTagPayload(NBTConstants.TYPE_COMPOUND, 0).toLinTag() instanceof LinCompoundTag lin)) { + throw new IOException("Data tag could not be read into LinCompoundTag"); + } + tag = lin; + } + default -> throw new IOException("Unexpected tag in compound: " + type); + } + } + if (id == null) { + throw new IOException("Missing Id tag in compound"); + } + if (x < 0 || y < 0 || z < 0) { + throw new IOException("Missing position for entity " + id); + } + if (tag == null) { + transformer.transform(x, y, z, id, LinCompoundTag.of(Map.of())); + continue; + } + tag = this.dataFixer.fixUp(fixType, tag); + if (tag == null) { + LOGGER.warn("Failed to fix-up entity for {} @ {},{},{} - skipping", id, x, y, z); + continue; + } + transformer.transform(x, y, z, id, tag); + } + } + + /** + * The `Palette` tag is required first, as that contains the information of the actual palette size. + * Keeping the whole Data block in memory - which *could* be compressed - is just not it + * + * @param paletteInitializer Invoked for each 'Palette' entry using the actual palette value (e.g. block state) + index + * @param paletteDataApplier Invoked for each 'Data' entry using the data index and the palette index at the data index + */ + private void readPalette( + boolean hasClipboard, + byte paletteType, + BooleanSupplier paletteAlreadyInitialized, + PaletteInitializer paletteInitializer, + PaletteDataApplier paletteDataApplier, + AdditionalTagConsumer additionalTag + ) throws IOException { + boolean hasPalette = paletteAlreadyInitialized.getAsBoolean(); + byte type; + String tag; + while ((type = this.dataInputStream.readByte()) != NBTConstants.TYPE_END) { + tag = this.dataInputStream.readUTF(); + if (tag.equals("Palette")) { + if (hasPalette) { + // Skip palette, as already exists + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_COMPOUND, 0); + continue; + } + if (!this.readPaletteMap(this.dataInputStream, paletteInitializer)) { + if (this.supportsReset()) { + // Couldn't read - skip palette for now + this.remainingTags.add(paletteType); + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_COMPOUND, 0); + continue; + } + // Reset not possible, write into cache + final NBTOutputStream cacheWriter = new NBTOutputStream(this.getPaletteCacheWriter()); + cacheWriter.write(paletteType); + cacheWriter.writeTagPayload(this.nbtInputStream.readTagPayload(NBTConstants.TYPE_COMPOUND, 0)); + continue; + } + hasPalette = true; + continue; + } + if (tag.equals("Data")) { + // No palette or dimensions are yet available + if (!hasPalette || this.dataFixer == null || !hasClipboard) { + if (this.supportsReset()) { + this.remainingTags.add(paletteType); + this.nbtInputStream.readTagPayloadLazy(NBTConstants.TYPE_BYTE_ARRAY, 0); + continue; + } + // Reset not possible, write into cache + int byteLen = this.dataInputStream.readInt(); + final DataOutputStream cacheWriter = new DataOutputStream(this.getDataCacheWriter()); + cacheWriter.write(paletteType); + cacheWriter.writeInt(byteLen); + IOUtil.copy(this.dataInputStream, cacheWriter, byteLen); + continue; + } + this.readPaletteData(this.dataInputStream, paletteDataApplier); + continue; + } + additionalTag.accept(type, tag); + } + } + + private void readPaletteData(DataInputStream stream, PaletteDataApplier applier) throws IOException { + int length = stream.readInt(); + // Write data into clipboard + int i = 0; + if (needsVarIntReading(length)) { + for (var iter = new VarIntStreamIterator(stream, length); iter.hasNext(); i++) { + applier.apply(i, (char) iter.nextInt()); + } + return; + } + while (i < length) { + applier.apply(i++, (char) stream.readUnsignedByte()); + } + } + + /** + * Reads the CompoundTag containing the palette mapping ({@code index: value}) and passes each entry to the + * {@link PaletteInitializer}. + *

+ * This method expects that the identifier ({@link NBTConstants#TYPE_COMPOUND}) is already consumed from the stream. + * + * @param stream The stream to read the data from. + * @param initializer The initializer called for each entry with its index and backed value. + * @return {@code true} if the mapping could be read, {@code false} otherwise (e.g. DataFixer is not yet available). + * @throws IOException on I/O error. + */ + private boolean readPaletteMap(DataInputStream stream, PaletteInitializer initializer) throws IOException { + if (this.dataFixer == null) { + return false; + } + while (stream.readByte() != NBTConstants.TYPE_END) { + String value = stream.readUTF(); + char index = (char) stream.readInt(); + initializer.initialize(index, value); + } + return true; + } + + private void indexToPosition(int index, PositionConsumer supplier) { + int y = index / (dimensions.x() * dimensions.z()); + int remainder = index - (y * dimensions.x() * dimensions.z()); + int z = remainder / dimensions.x(); + int x = remainder - z * dimensions.x(); + supplier.accept(x, y, z); + } + + private PaletteDataApplier getBlockWriter(Clipboard target) { + if (target instanceof LinearClipboard linearClipboard) { + return (index, ordinal) -> linearClipboard.setBlock(index, this.blockPalette[ordinal]); + } + return (index, ordinal) -> indexToPosition(index, (x, y, z) -> target.setBlock(x, y, z, this.blockPalette[ordinal])); + } + + private PaletteDataApplier getBiomeWriter(Clipboard target) { + return (index, ordinal) -> indexToPosition(index, (x, y, z) -> target.setBiome(x, y, z, this.biomePalette[ordinal])); + } + + private PaletteInitializer provideBlockPaletteInitializer() { + return (index, value) -> { + if (this.dataFixer == null) { + throw new IllegalStateException("Can't read block palette map if DataFixer is not yet available"); + } + value = dataFixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value); + try { + this.blockPalette[index] = BlockState.get(value); + } catch (InputParseException e) { + LOGGER.warn("Invalid BlockState in palette: {}. Block will be replaced with air.", value); + this.blockPalette[index] = BlockTypes.AIR.getDefaultState(); + } + }; + } + + private PaletteInitializer provideBiomePaletteInitializer() { + return (index, value) -> { + if (this.dataFixer == null) { + throw new IllegalStateException("Can't read biome palette map if DataFixer is not yet available"); + } + value = dataFixer.fixUp(DataFixer.FixTypes.BIOME, value); + BiomeType biomeType = BiomeTypes.get(value); + if (biomeType == null) { + biomeType = BiomeTypes.PLAINS; + LOGGER.warn("Invalid biome type in palette: {}. Biome will be replaced with plains.", value); + } + this.biomePalette[index] = biomeType; + }; + } + + private EntityTransformer provideEntityTransformer(Clipboard clipboard) { + return (x, y, z, id, tag) -> { + EntityType type = EntityType.REGISTRY.get(id); + if (type == null) { + LOGGER.warn("Invalid entity id: {} - skipping", id); + return; + } + clipboard.createEntity( + new Location(clipboard, Location.at(x, y, z).add(clipboard.getMinimumPoint().toVector3())), + new BaseEntity(type, LazyReference.computed(tag)) + ); + }; + } + + private EntityTransformer provideTileEntityTransformer(Clipboard clipboard) { + return (x, y, z, id, tag) -> clipboard.tile( + MathMan.roundInt(x + clipboard.getMinimumPoint().x()), + MathMan.roundInt(y + clipboard.getMinimumPoint().y()), + MathMan.roundInt(z + clipboard.getMinimumPoint().z()), + FaweCompoundTag.of(tag) + ); + } + + /** + * @return {@code true} if {@code Width}, {@code Length} and {@code Height} are already read from the stream + */ + private boolean areDimensionsAvailable() { + return this.dimensions.x() != 0 && this.dimensions.y() != 0 && this.dimensions.z() != 0; + } + + /** + * Closes this reader instance and all underlying resources. + * + * @throws IOException on I/O error. + */ + @Override + public void close() throws IOException { + parentStream.close(); // closes all underlying resources implicitly + } + + /** + * Resets the main stream to the previously marked position ({@code 0}), if supported (see {@link #supportsReset()}). + * If the stream is reset, the sub streams (for DataInput and NBT) are re-created to respect the new position. + * + * @throws IOException on I/O error. + */ + private void reset() throws IOException { + if (this.supportsReset()) { + this.parentStream.reset(); + this.parentStream.mark(Integer.MAX_VALUE); + this.setSubStreams(); + } + } + + /** + * @return {@code true} if the stream used while instantiating the reader supports resets (without memory overhead). + */ + private boolean supportsReset() { + return this.remainingTags != null; + } + + /** + * Overwrites the DataInput- and NBT-InputStreams (e.g. when the marker of the backed stream updated). + * + * @throws IOException on I/O error. + */ + private void setSubStreams() throws IOException { + final FastBufferedInputStream buffer = new FastBufferedInputStream(new GZIPInputStream(this.parentStream)); + this.dataInputStream = new DataInputStream(buffer); + this.nbtInputStream = new NBTInputStream(buffer); + } + + /** + * Creates a new cache writer for non-palette data, if none exists yet. + * Returns either the already created or new one. + * + * @return the output stream for non-palette cache data. + */ + private OutputStream getDataCacheWriter() { + if (this.dataCacheWriter == null) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(512); + this.dataCacheWriter = new FastBufferedOutputStream(new LZ4BlockOutputStream(byteArrayOutputStream)) { + @Override + public void close() throws IOException { + this.write(CACHE_IDENTIFIER_END); + super.close(); + FastSchematicReaderV3.this.dataCache = byteArrayOutputStream.toByteArray(); + } + }; + } + return this.dataCacheWriter; + } + + /** + * Creates a new cache writer for palette data, if none exists yet. + * Returns either the already created or new one. + * + * @return the output stream for palette cache data. + */ + private OutputStream getPaletteCacheWriter() { + if (this.paletteCacheWriter == null) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(256); + this.paletteCacheWriter = new FastBufferedOutputStream(new LZ4BlockOutputStream(byteArrayOutputStream)) { + @Override + public void close() throws IOException { + this.write(CACHE_IDENTIFIER_END); + super.close(); + FastSchematicReaderV3.this.paletteCache = byteArrayOutputStream.toByteArray(); + } + }; + } + return this.paletteCacheWriter; + } + + private boolean needsVarIntReading(int byteArrayLength) { + return byteArrayLength > this.dimensions.x() * this.dimensions.y() * this.dimensions.z(); + } + + /** + * Skips the schematic header including the root compound (empty name) and the root's child compound ("Schematic") + * + * @param dataInputStream The stream containing the schematic data to skip + * @throws IOException on I/O error + */ + private static void skipHeader(DataInputStream dataInputStream) throws IOException { + dataInputStream.skipNBytes(1 + 2); // 1 Byte = TAG_Compound, 2 Bytes = Short (Length of tag name = "") + dataInputStream.skipNBytes(1 + 2 + 9); // as above + 9 bytes = "Schematic" + } + + @ApiStatus.Internal + @FunctionalInterface + private interface PositionConsumer { + + /** + * Called with block location coordinates. + * + * @param x the x coordinate. + * @param y the y coordinate. + * @param z the z coordinate. + */ + void accept(int x, int y, int z); + + } + + @ApiStatus.Internal + @FunctionalInterface + private interface EntityTransformer { + + /** + * Called for each entity from the Schematics {@code Entities} compound list. + * + * @param x the relative x coordinate of the entity. + * @param y the relative y coordinate of the entity. + * @param z the relative z coordinate of the entity. + * @param id the entity id as a resource location (e.g. {@code minecraft:sheep}). + * @param tag the - already fixed, if required - nbt data of the entity. + */ + void transform(double x, double y, double z, String id, LinCompoundTag tag); + + } + + @ApiStatus.Internal + @FunctionalInterface + private interface PaletteInitializer { + + /** + * Called for each palette entry (the mapping part, not data). + * + * @param index the index of the entry, as used in the Data byte array. + * @param value the value for this entry (either biome type as resource location or the block state as a string). + */ + void initialize(char index, String value); + + } + + @ApiStatus.Internal + @FunctionalInterface + private interface PaletteDataApplier { + + /** + * Called for each palette data entry (not the mapping part, but the var-int byte array). + * + * @param index The index of this data entry (due to var-int behaviour not necessarily the index in the data byte array). + * @param ordinal The ordinal of this entry as defined in the palette mapping. + */ + void apply(int index, char ordinal); + + } + + @ApiStatus.Internal + @FunctionalInterface + private interface AdditionalTagConsumer { + + /** + * Called for each unknown nbt tag. + * + * @param type The type of the tag (as defined by the constants in {@link NBTConstants}). + * @param name The name of the tag. + */ + void accept(byte type, String name); + + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV2.java similarity index 92% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriter.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV2.java index db3452d29..3bd302876 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV2.java @@ -48,9 +48,9 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Writes schematic files using the Sponge schematic format. */ -public class FastSchematicWriter implements ClipboardWriter { +public class FastSchematicWriterV2 implements ClipboardWriter { - private static final int CURRENT_VERSION = 2; + public static final int CURRENT_VERSION = 2; private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE; private final NBTOutputStream outputStream; @@ -61,7 +61,7 @@ public class FastSchematicWriter implements ClipboardWriter { * * @param outputStream the output stream to write to */ - public FastSchematicWriter(NBTOutputStream outputStream) { + public FastSchematicWriterV2(NBTOutputStream outputStream) { checkNotNull(outputStream); this.outputStream = outputStream; } @@ -103,26 +103,26 @@ public class FastSchematicWriter implements ClipboardWriter { final DataOutput rawStream = outputStream.getOutputStream(); outputStream.writeLazyCompoundTag("Schematic", out -> { + out.writeNamedTag("Version", CURRENT_VERSION); out.writeNamedTag( "DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion() ); - out.writeNamedTag("Version", CURRENT_VERSION); out.writeNamedTag("Width", (short) width); out.writeNamedTag("Height", (short) height); out.writeNamedTag("Length", (short) length); // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' out.writeNamedTag("Offset", new int[]{ - min.getBlockX(), - min.getBlockY(), - min.getBlockZ(), + min.x(), + min.y(), + min.z(), }); out.writeLazyCompoundTag("Metadata", out1 -> { - out1.writeNamedTag("WEOffsetX", offset.getBlockX()); - out1.writeNamedTag("WEOffsetY", offset.getBlockY()); - out1.writeNamedTag("WEOffsetZ", offset.getBlockZ()); + out1.writeNamedTag("WEOffsetX", offset.x()); + out1.writeNamedTag("WEOffsetY", offset.y()); + out1.writeNamedTag("WEOffsetZ", offset.z()); out1.writeNamedTag("FAWEVersion", Fawe.instance().getVersion().build); }); @@ -149,7 +149,7 @@ public class FastSchematicWriter implements ClipboardWriter { BaseBlock block = pos.getFullBlock(finalClipboard); CompoundTag nbt = block.getNbtData(); if (nbt != null) { - Map values = new HashMap<>(nbt.getValue()); + Map> values = new HashMap<>(nbt.getValue()); // Positions are kept in NBT, we don't want that. values.remove("x"); @@ -162,9 +162,9 @@ public class FastSchematicWriter implements ClipboardWriter { // Dum. values.remove("id"); values.put("Pos", new IntArrayTag(new int[]{ - pos.getX(), - pos.getY(), - pos.getZ() + pos.x(), + pos.y(), + pos.z() })); numTiles++; @@ -223,7 +223,7 @@ public class FastSchematicWriter implements ClipboardWriter { BaseEntity state = entity.getState(); if (state != null) { - Map values = new HashMap<>(); + Map> values = new HashMap<>(); // Put NBT provided data CompoundTag rawTag = state.getNbtData(); @@ -237,7 +237,7 @@ public class FastSchematicWriter implements ClipboardWriter { if (!brokenEntities) { loc = loc.setPosition(loc.add(min.toVector3())); } - values.put("Id", new StringTag(state.getType().getId())); + values.put("Id", new StringTag(state.getType().id())); values.put("Pos", writeVector(loc)); values.put("Rotation", writeRotation(entity.getLocation())); @@ -282,10 +282,10 @@ public class FastSchematicWriter implements ClipboardWriter { int length = clipboard.getRegion().getLength(); MutableBlockVector3 mutable = new MutableBlockVector3(); for (int z = 0, i = 0; z < length; z++) { - int z0 = min.getBlockZ() + z; + int z0 = min.z() + z; for (int x = 0; x < width; x++, i++) { - int x0 = min.getBlockX() + x; - BiomeType biome = clipboard.getBiome(mutable.setComponents(x0, min.getY(), z0)); + int x0 = min.x() + x; + BiomeType biome = clipboard.getBiome(mutable.setComponents(x0, min.y(), z0)); task.applyInt(i, biome.getInternalId()); } } @@ -297,7 +297,7 @@ public class FastSchematicWriter implements ClipboardWriter { for (int i = 0; i < paletteList.size(); i++) { int ordinal = paletteList.get(i); BiomeType state = BiomeTypes.get(ordinal); - out12.writeNamedTag(state.getId(), i); + out12.writeNamedTag(state.id(), i); } }); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV3.java new file mode 100644 index 000000000..1d1f0df2a --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicWriterV3.java @@ -0,0 +1,295 @@ +package com.fastasyncworldedit.core.extent.clipboard.io; + +import com.fastasyncworldedit.core.function.visitor.Order; +import com.fastasyncworldedit.core.util.IOUtil; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.NBTConstants; +import com.sk89q.jnbt.NBTOutputStream; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import net.jpountz.lz4.LZ4BlockInputStream; +import net.jpountz.lz4.LZ4BlockOutputStream; +import org.enginehub.linbus.tree.LinCompoundTag; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +/** + * Faster, stream-based implementation of {@link com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Writer} for + * writing schematics conforming the sponge schematic v3 format. + * + * @since 2.11.1 + */ +@SuppressWarnings("removal") // Yes, JNBT is deprecated - we know +public class FastSchematicWriterV3 implements ClipboardWriter { + + public static final int CURRENT_VERSION = 3; + + private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE; + private final NBTOutputStream outputStream; + + + public FastSchematicWriterV3(final NBTOutputStream outputStream) { + this.outputStream = Objects.requireNonNull(outputStream, "outputStream"); + } + + @Override + public void write(final Clipboard clipboard) throws IOException { + clipboard.flush(); + + // Validate dimensions before starting to write into stream + final Region region = clipboard.getRegion(); + if (region.getWidth() > MAX_SIZE) { + throw new IllegalArgumentException("Region width too large for schematic: " + region.getWidth()); + } + if (region.getHeight() > MAX_SIZE) { + throw new IllegalArgumentException("Region height too large for schematic: " + region.getHeight()); + } + if (region.getLength() > MAX_SIZE) { + throw new IllegalArgumentException("Region length too large for schematic: " + region.getLength()); + } + + this.outputStream.writeLazyCompoundTag( + "", root -> root.writeLazyCompoundTag("Schematic", out -> this.write2(out, clipboard)) + ); + } + + private void write2(NBTOutputStream schematic, Clipboard clipboard) throws IOException { + final Region region = clipboard.getRegion(); + final BlockVector3 origin = clipboard.getOrigin(); + final BlockVector3 min = clipboard.getMinimumPoint(); + final BlockVector3 offset = min.subtract(origin); + + schematic.writeNamedTag("Version", CURRENT_VERSION); + schematic.writeNamedTag( + "DataVersion", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion() + ); + schematic.writeLazyCompoundTag("Metadata", out -> this.writeMetadata(out, clipboard)); + + schematic.writeNamedTag("Width", (short) region.getWidth()); + schematic.writeNamedTag("Height", (short) region.getHeight()); + schematic.writeNamedTag("Length", (short) region.getLength()); + + schematic.writeNamedTag("Offset", new int[]{ + offset.x(), offset.y(), offset.z() + }); + + schematic.writeLazyCompoundTag("Blocks", out -> this.writeBlocks(out, clipboard)); + if (clipboard.hasBiomes()) { + schematic.writeLazyCompoundTag("Biomes", out -> this.writeBiomes(out, clipboard)); + } + // Some clipboards have quite heavy operations on the getEntities method - only call once + List entities; + if (!(entities = clipboard.getEntities()).isEmpty()) { + schematic.writeNamedTagName("Entities", NBTConstants.TYPE_LIST); + schematic.write(NBTConstants.TYPE_COMPOUND); + schematic.writeInt(entities.size()); + for (final Entity entity : entities) { + this.writeEntity(schematic, clipboard, entity); + } + } + } + + private void writeBlocks(NBTOutputStream blocks, Clipboard clipboard) throws IOException { + final int[] tiles = new int[]{0}; + final ByteArrayOutputStream tileBytes = new ByteArrayOutputStream(); + try (LZ4BlockOutputStream lz4Stream = new LZ4BlockOutputStream(tileBytes); + NBTOutputStream tileOut = new NBTOutputStream(lz4Stream)) { + this.writePalette( + blocks, + BlockTypesCache.states.length, + pos -> { + BaseBlock block = pos.getFullBlock(clipboard); + LinCompoundTag tag; + if ((tag = block.getNbt()) != null) { + tiles[0]++; + try { + tileOut.writeNamedTag("Id", block.getNbtId()); + tileOut.writeNamedTag("Pos", new int[]{ + pos.x() - clipboard.getMinimumPoint().x(), + pos.y() - clipboard.getMinimumPoint().y(), + pos.z() - clipboard.getMinimumPoint().z() + }); + //noinspection deprecation + tileOut.writeNamedTag("Data", new CompoundTag(tag)); + tileOut.write(NBTConstants.TYPE_END); + } catch (IOException e) { + throw new RuntimeException("Failed to write tile data", e); + } + } + return block; + }, + block -> { + char ordinal = block.getOrdinalChar(); + if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { + ordinal = BlockTypesCache.ReservedIDs.AIR; + } + return ordinal; + }, + BlockStateHolder::getAsString, + clipboard + ); + lz4Stream.finish(); + } finally { + // Write Tiles + if (tiles[0] > 0) { + blocks.writeNamedTagName("BlockEntities", NBTConstants.TYPE_LIST); + blocks.write(NBTConstants.TYPE_COMPOUND); + blocks.writeInt(tiles[0]); + // Decompress cached data again + try (LZ4BlockInputStream reader = new LZ4BlockInputStream(new ByteArrayInputStream(tileBytes.toByteArray()))) { + IOUtil.copy(reader, blocks.getOutputStream()); + } + } + } + } + + private void writeBiomes(NBTOutputStream biomes, Clipboard clipboard) throws IOException { + this.writePalette( + biomes, BiomeType.REGISTRY.size(), + pos -> pos.getBiome(clipboard), + biome -> (char) biome.getInternalId(), + BiomeType::id, + clipboard + ); + } + + private void writeEntity(NBTOutputStream out, Clipboard clipboard, Entity entity) throws IOException { + final BaseEntity state = entity.getState(); + if (state == null) { + throw new IOException("Entity has no state"); + } + out.writeNamedTag("Id", state.getType().id()); + + out.writeNamedTagName("Pos", NBTConstants.TYPE_LIST); + out.write(NBTConstants.TYPE_DOUBLE); + out.writeInt(3); + out.writeDouble(entity.getLocation().x() - clipboard.getMinimumPoint().x()); + out.writeDouble(entity.getLocation().y() - clipboard.getMinimumPoint().y()); + out.writeDouble(entity.getLocation().z() - clipboard.getMinimumPoint().z()); + + out.writeLazyCompoundTag("Data", data -> { + //noinspection deprecation + CompoundTag nbt = state.getNbtData(); + if (nbt != null) { + nbt.getValue().forEach((s, tag) -> { + if (s.equals("id") || s.equals("Rotation")) { + return; + } + try { + data.writeNamedTag(s, tag); + } catch (IOException e) { + throw new RuntimeException("failed to write entity data", e); + } + }); + } + + // Write rotation list + data.writeNamedTagName("Rotation", NBTConstants.TYPE_LIST); + data.write(NBTConstants.TYPE_FLOAT); + data.writeInt(2); + data.writeFloat(entity.getLocation().getYaw()); + data.writeFloat(entity.getLocation().getPitch()); + }); + + out.write(NBTConstants.TYPE_END); // End the compound + } + + private void writePalette( + NBTOutputStream out, int capacity, + Function objectResolver, + Function ordinalResolver, + Function paletteEntryResolver, + Clipboard clipboard + ) throws IOException { + int dataBytesUsed = 0; + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + try (LZ4BlockOutputStream dataOut = new LZ4BlockOutputStream(bytes)) { + int index = 0; + char[] palette = new char[capacity]; + Arrays.fill(palette, Character.MAX_VALUE); + final Iterator iterator = clipboard.iterator(Order.YZX); + // Start Palette tag + out.writeNamedTagName("Palette", NBTConstants.TYPE_COMPOUND); + while (iterator.hasNext()) { + BlockVector3 pos = iterator.next(); + T obj = objectResolver.apply(pos); + char ordinal = ordinalResolver.apply(obj); + char value = palette[ordinal]; + if (value == Character.MAX_VALUE) { + palette[ordinal] = value = (char) index++; + if (index >= palette.length) { + throw new IOException("insufficient palette capacity: " + palette.length + ", index: " + index); + } + out.writeNamedTag(paletteEntryResolver.apply(obj), value); + } + if ((value & -128) != 0) { + dataBytesUsed++; + dataOut.write(value & 127 | 128); + value >>>= 7; + } + dataOut.write(value); + dataBytesUsed++; + } + // End Palette tag + out.write(NBTConstants.TYPE_END); + dataOut.finish(); + } finally { + // Write Data tag + if (dataBytesUsed > 0) { + try (LZ4BlockInputStream reader = new LZ4BlockInputStream(new ByteArrayInputStream(bytes.toByteArray()))) { + out.writeNamedTagName("Data", NBTConstants.TYPE_BYTE_ARRAY); + out.writeInt(dataBytesUsed); + IOUtil.copy(reader, (DataOutput) out); + } + } + } + } + + private void writeMetadata(NBTOutputStream metadata, Clipboard clipboard) throws IOException { + metadata.writeNamedTag("Date", System.currentTimeMillis()); + metadata.writeLazyCompoundTag("WorldEdit", out -> { + out.writeNamedTag("Version", WorldEdit.getVersion()); + out.writeNamedTag( + "EditingPlatform", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getId() + ); + out.writeNamedTag("Origin", new int[]{ + clipboard.getOrigin().x(), clipboard.getOrigin().y(), clipboard.getOrigin().z() + }); + out.writeLazyCompoundTag("Platforms", platforms -> { + for (final Platform platform : WorldEdit.getInstance().getPlatformManager().getPlatforms()) { + platforms.writeLazyCompoundTag(platform.getId(), p -> { + p.writeNamedTag("Name", platform.getPlatformName()); + p.writeNamedTag("Version", platform.getPlatformVersion()); + }); + } + }); + }); + } + + @Override + public void close() throws IOException { + this.outputStream.close(); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java index 66deefeb7..0915766cc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/MinecraftStructure.java @@ -19,7 +19,6 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.AbstractProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.block.BaseBlock; @@ -71,7 +70,7 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { throw new IOException("Root tag has name - are you sure this is a structure?"); } - Map tags = ((CompoundTag) rootTag.getTag()).getValue(); + Map> tags = ((CompoundTag) rootTag.getTag()).getValue(); ListTag size = (ListTag) tags.get("size"); int width = size.getInt(0); @@ -90,13 +89,13 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { BlockState[] combinedArray = new BlockState[palette.size()]; for (int i = 0; i < palette.size(); i++) { CompoundTag compound = palette.get(i); - Map map = compound.getValue(); + Map> map = compound.getValue(); String name = ((StringTag) map.get("Name")).getValue(); BlockType type = BlockTypes.get(name); BlockState state = type.getDefaultState(); CompoundTag properties = (CompoundTag) map.get("Properties"); if (properties != null) { - for (Map.Entry entry : properties.getValue().entrySet()) { + for (Map.Entry> entry : properties.getValue().entrySet()) { String key = entry.getKey(); String value = ((StringTag) entry.getValue()).getValue(); Property property = type.getProperty(key); @@ -109,7 +108,7 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { List blocksList = (List) tags.get("blocks").getValue(); try { for (CompoundTag compound : blocksList) { - Map blockMap = compound.getValue(); + Map> blockMap = compound.getValue(); IntTag stateTag = (IntTag) blockMap.get("state"); ListTag posTag = (ListTag) blockMap.get("pos"); BlockState state = combinedArray[stateTag.getValue()]; @@ -137,7 +136,7 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { if (entities != null) { List entityList = (List) (List) entities.getValue(); for (CompoundTag entityEntry : entityList) { - Map entityEntryMap = entityEntry.getValue(); + Map> entityEntryMap = entityEntry.getValue(); ListTag posTag = (ListTag) entityEntryMap.get("pos"); CompoundTag nbtTag = (CompoundTag) entityEntryMap.get("nbt"); String id = nbtTag.getString("Id"); @@ -174,27 +173,23 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { ArrayList> palette = new ArrayList<>(); for (BlockVector3 point : region) { BlockState block = clipboard.getBlock(point); - int combined = block.getInternalId(); + char ordinal = block.getOrdinalChar(); BlockType type = block.getBlockType(); - if (type == BlockTypes.STRUCTURE_VOID || indexes.containsKey(combined)) { + if (type == BlockTypes.STRUCTURE_VOID || indexes.containsKey(ordinal)) { continue; } - indexes.put(combined, (Integer) palette.size()); + indexes.put(ordinal, palette.size()); HashMap paletteEntry = new HashMap<>(); - paletteEntry.put("Name", type.getId()); + paletteEntry.put("Name", type.id()); if (block.getInternalId() != type.getInternalId()) { Map properties = null; - for (AbstractProperty property : (List>) type.getProperties()) { - int propIndex = property.getIndex(block.getInternalId()); - if (propIndex != 0) { - if (properties == null) { - properties = new HashMap<>(); - } - Object value = property.getValues().get(propIndex); - properties.put(property.getName(), value.toString()); + for (Map.Entry, Object> entry : block.getStates().entrySet()) { + if (properties == null) { + properties = new HashMap<>(); } + properties.put(entry.getKey().getName(), entry.getValue().toString()); } if (properties != null) { paletteEntry.put("Properties", properties); @@ -211,16 +206,23 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { for (BlockVector3 point : region) { BaseBlock block = clipboard.getFullBlock(point); if (block.getBlockType() != BlockTypes.STRUCTURE_VOID) { - int combined = block.getInternalId(); - int index = indexes.get(combined); - List pos = Arrays.asList(point.getX() - min.getX(), - point.getY() - min.getY(), point.getZ() - min.getZ() + char ordinal = block.getOrdinalChar(); + int index = indexes.get(ordinal); + List pos = Arrays.asList( + point.x() - min.x(), + point.y() - min.y(), + point.z() - min.z() ); if (!block.hasNbtData()) { blocks.add(FaweCache.INSTANCE.asMap("state", index, "pos", pos)); } else { + Map> tag = new HashMap<>(block.getNbtData().getValue()); + tag.remove("x"); + tag.remove("y"); + tag.remove("z"); + CompoundTag cTag = new CompoundTag(tag); blocks.add( - FaweCache.INSTANCE.asMap("state", index, "pos", pos, "nbt", block.getNbtData())); + FaweCache.INSTANCE.asMap("state", index, "pos", pos, "nbt", cTag)); } } } @@ -231,16 +233,24 @@ public class MinecraftStructure implements ClipboardReader, ClipboardWriter { ArrayList> entities = new ArrayList<>(); for (Entity entity : clipboard.getEntities()) { Location loc = entity.getLocation(); - List pos = Arrays.asList(loc.getX(), loc.getY(), loc.getZ()); - List blockPos = Arrays.asList(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + List pos = Arrays.asList( + loc.x() - min.x(), + loc.y() - min.y(), + loc.z() - min.z() + ); + List blockPos = Arrays.asList( + loc.getBlockX() - min.x(), + loc.getBlockY() - min.y(), + loc.getBlockZ() - min.z() + ); BaseEntity state = entity.getState(); if (state != null) { CompoundTag nbt = state.getNbtData(); - Map nbtMap = nbt.getValue(); + Map> nbtMap = new HashMap<>(nbt.getValue()); // Replace rotation data nbtMap.put("Rotation", writeRotation(entity.getLocation())); - nbtMap.put("id", new StringTag(state.getType().getId())); - Map entityMap = FaweCache.INSTANCE.asMap("pos", pos, "blockPos", blockPos, "nbt", nbt); + nbtMap.put("id", new StringTag(state.getType().id())); + Map entityMap = FaweCache.INSTANCE.asMap("pos", pos, "blockPos", blockPos, "nbt", new CompoundTag(nbtMap)); entities.add(entityMap); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/PNGWriter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/PNGWriter.java index b5cbc7fb2..48a3315d5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/PNGWriter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/schematic/PNGWriter.java @@ -75,9 +75,9 @@ public class PNGWriter implements ClipboardWriter { MutableBlockVector3 mutableLeft = new MutableBlockVector3(0, 0, 0); BlockVector3 min = clipboard.getMinimumPoint(); - int y0 = min.getBlockY(); - int z0 = min.getBlockZ(); - int x0 = min.getBlockX(); + int y0 = min.y(); + int z0 = min.z(); + int x0 = min.x(); for (int x = x0; x < x0 + width; x++) { mutable.mutX(x); mutableTop.mutX(x); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/ArrayImageMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/ArrayImageMask.java index 4976af5f7..07c9acac1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/ArrayImageMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/ArrayImageMask.java @@ -20,7 +20,7 @@ public class ArrayImageMask implements FilterBlockMask { @Override public boolean applyBlock(FilterBlock block) { - int height = image.getRGB(block.getX(), block.getZ()) & 0xFF; + int height = image.getRGB(block.x(), block.z()) & 0xFF; return height == 255 || height > 0 && !white && random.nextInt(256) <= height; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java index 72ee73013..7c6767bf2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java @@ -1,8 +1,11 @@ package com.fastasyncworldedit.core.extent.filter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; -public class CountFilter extends ForkedFilter { +public class CountFilter extends ForkedFilter implements VectorizedFilter { private int total; @@ -33,4 +36,10 @@ public class CountFilter extends ForkedFilter { return total; } + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask mask) { + total += mask.trueCount(); + return set; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java index 25627c451..ff57a4625 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java @@ -1,37 +1,93 @@ package com.fastasyncworldedit.core.extent.filter; -import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.fastasyncworldedit.core.queue.Filter; +import com.fastasyncworldedit.core.queue.IChunk; +import com.sk89q.worldedit.regions.Region; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import org.jetbrains.annotations.Nullable; /** - * Filter which links two Filters together for single-filter-input operations. + * Filter which links two Filters together for single-filter-input operations. Left filter is operated first. * - * @param Parent which extends Filter - * @param Child which extends Filter + * @param Left filter + * @param Right filter */ -public final class LinkedFilter extends DelegateFilter { +public sealed class LinkedFilter implements Filter { - private final S child; + private final L left; + private final R right; - public LinkedFilter(T parent, S child) { - super(parent); - this.child = child; + public LinkedFilter(L left, R right) { + this.left = left; + this.right = right; } - public S getChild() { - return this.child; + @SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system + public static LinkedFilter of(L left, R right) { + if (left instanceof VectorizedFilter l && right instanceof VectorizedFilter r) { + return new VectorizedLinkedFilter(l, r); + } + return new LinkedFilter<>(left, right); + } + + public L getLeft() { + return this.left; + } + + public R getRight() { + return this.right; + } + + @Override + public T applyChunk(T chunk, @Nullable Region region) { + chunk = getLeft().applyChunk(chunk, region); + return getRight().applyChunk(chunk, region); } @Override public void applyBlock(FilterBlock block) { - this.getParent().applyBlock(block); - this.getChild().applyBlock(block); + getLeft().applyBlock(block); + getRight().applyBlock(block); } @Override - public LinkedFilter, Filter> newInstance(Filter other) { - return new LinkedFilter<>(this, other); + public void finishChunk(IChunk chunk) { + getLeft().finishChunk(chunk); + getRight().finishChunk(chunk); + } + + @Override + public Filter fork() { + return new LinkedFilter<>(getLeft().fork(), getRight().fork()); + } + + @Override + public void join() { + getLeft().join(); + getRight().join(); + } + + private final static class VectorizedLinkedFilter + extends LinkedFilter implements VectorizedFilter { + + public VectorizedLinkedFilter(final L left, final R right) { + super(left, right); + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask mask) { + ShortVector res = getLeft().applyVector(get, set, mask); + return getRight().applyVector(get, res, mask); + } + + @Override + public Filter fork() { + return new VectorizedLinkedFilter<>((L) getLeft().fork(), (R) getRight().fork()); + } + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java index 9284f8378..2ce1527df 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java @@ -2,10 +2,17 @@ package com.fastasyncworldedit.core.extent.filter; import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; /** @@ -15,8 +22,8 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class MaskFilter extends DelegateFilter { - private final Mask mask; - private final AtomicInteger changes; + final Mask mask; + final AtomicInteger changes; public MaskFilter(T other, Mask root) { this(other, root, new AtomicInteger()); @@ -60,4 +67,44 @@ public class MaskFilter extends DelegateFilter { return new MaskFilter<>(getParent().fork(), mask.copy(), changes); } + public static class VectorizedMaskFilter extends MaskFilter implements VectorizedFilter { + + private final VectorizedMask vectorizedMask; + + public VectorizedMaskFilter(final T other, final Mask root) { + super(other, root); + this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask"); + } + + public VectorizedMaskFilter(final T other, final Mask root, AtomicInteger changes) { + super(other, root, changes); + this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask"); + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask mask) { + final T parent = getParent(); + VectorMask masked = vectorizedMask.compareVector(set, get); + ShortVector res = parent.applyVector(get, set, mask.and(masked)); + VectorMask changed = res.compare(VectorOperators.NE, set); + changes.getAndAdd(changed.trueCount()); + return res; + } + + @Override + public MaskFilter newInstance(final Filter other) { + if (other instanceof VectorizedFilter o) { + return new VectorizedMaskFilter<>(o, mask); + } + return super.newInstance(other); + } + + @SuppressWarnings("unchecked") + @Override + public Filter fork() { + return new VectorizedMaskFilter<>((T) getParent().fork(), mask.copy(), changes); + } + + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractFilterBlock.java index b91ef08b0..4f3db3994 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractFilterBlock.java @@ -31,18 +31,18 @@ public abstract class AbstractFilterBlock extends FilterBlock { public abstract Extent getExtent(); @Override - public int getX() { - return getPosition().getX(); + public int x() { + return getPosition().x(); } @Override - public int getY() { - return getPosition().getY(); + public int y() { + return getPosition().y(); } @Override - public int getZ() { - return getPosition().getZ(); + public int z() { + return getPosition().z(); } @Override @@ -72,12 +72,12 @@ public abstract class AbstractFilterBlock extends FilterBlock { @Override public BlockVector3 getMinimumPoint() { - return at(getX(), getY(), getZ()); + return at(x(), y(), z()); } @Override public BlockVector3 getMaximumPoint() { - return at(getX(), getY(), getZ()); + return at(x(), y(), z()); } @Override @@ -88,7 +88,7 @@ public abstract class AbstractFilterBlock extends FilterBlock { @Override public > boolean setBlock(int x, int y, int z, T block) throws WorldEditException { - if (x == this.getX() && y == this.getY() && z == this.getZ()) { + if (x == this.x() && y == this.y() && z == this.z()) { setFullBlock(block.toBaseBlock()); return true; } @@ -97,7 +97,7 @@ public abstract class AbstractFilterBlock extends FilterBlock { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - if (x == this.getX() && y == this.getY() && z == this.getZ()) { + if (x == this.x() && y == this.y() && z == this.z()) { setBiome(biome); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractSingleFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractSingleFilterBlock.java index 95e50dc76..5d64ead7c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractSingleFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/AbstractSingleFilterBlock.java @@ -83,18 +83,18 @@ public abstract class AbstractSingleFilterBlock extends FilterBlock { @Override public BlockVector3 getMinimumPoint() { - return at(getX(), getY(), getZ()); + return at(x(), y(), z()); } @Override public BlockVector3 getMaximumPoint() { - return at(getX(), getY(), getZ()); + return at(x(), y(), z()); } @Override public > boolean setBlock(int x, int y, int z, T block) throws WorldEditException { - if (x == this.getX() && y == this.getY() && z == this.getZ()) { + if (x == this.x() && y == this.y() && z == this.z()) { setFullBlock(block.toBaseBlock()); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java index 4f73d5fa3..2e9263cea 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.extent.filter.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; @@ -80,17 +81,17 @@ public class ArrayFilterBlock extends AbstractExtentFilterBlock { } @Override - public int getX() { + public int x() { return x; } @Override - public int getY() { + public int y() { return (heights[index] & 0xFF) + yOffset; } @Override - public int getZ() { + public int z() { return z; } @@ -105,6 +106,11 @@ public class ArrayFilterBlock extends AbstractExtentFilterBlock { return getExtent().setBlock(x, y, z, block); } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + return false; // class is unused + deprecated, do not care about impl + } + @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { return getExtent().setBiome(x, y, z, biome); @@ -112,12 +118,12 @@ public class ArrayFilterBlock extends AbstractExtentFilterBlock { @Override public void setBiome(final BiomeType biome) { - getExtent().setBiome(getX(), getY(), getZ(), biome); + getExtent().setBiome(x(), y(), z(), biome); } @Override public BiomeType getBiome() { - return getExtent().getBiomeType(getX(), getY(), getZ()); + return getExtent().getBiomeType(x(), y(), z()); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java index 9a339826a..718171efd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.extent.filter.block; import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.FilterBlockMask; import com.fastasyncworldedit.core.queue.IBlocks; @@ -8,11 +9,11 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.Flood; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -20,12 +21,15 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.registry.BlockMaterial; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.jetbrains.annotations.ApiStatus; import javax.annotation.Nonnull; import javax.annotation.Nullable; import static com.sk89q.worldedit.world.block.BlockTypesCache.states; +@ApiStatus.NonExtendable public class CharFilterBlock extends ChunkFilterBlock { private static final SetDelegate FULL = (block, value) -> block.setArr[block.index] = value; @@ -35,10 +39,10 @@ public class CharFilterBlock extends ChunkFilterBlock { private int minLayer; private CharGetBlocks get; private IChunkSet set; - private char[] getArr; + protected char[] getArr; @Nullable - private char[] setArr; - private SetDelegate delegate; + protected char[] setArr; + protected SetDelegate delegate; // local private int layer; private int index; @@ -169,7 +173,7 @@ public class CharFilterBlock extends ChunkFilterBlock { } @Override - public synchronized final void filter(Filter filter) { + public synchronized void filter(Filter filter) { for (y = 0, index = 0; y < 16; y++) { for (z = 0; z < 16; z++) { for (x = 0; x < 16; x++, index++) { @@ -190,17 +194,17 @@ public class CharFilterBlock extends ChunkFilterBlock { } @Override - public final int getX() { + public final int x() { return xx + x; } @Override - public final int getY() { + public final int y() { return yy + y; } @Override - public final int getZ() { + public final int z() { return zz + z; } @@ -259,8 +263,8 @@ public class CharFilterBlock extends ChunkFilterBlock { final BlockState state = getBlock(); final BlockMaterial material = state.getMaterial(); if (material.hasContainer()) { - final CompoundTag tag = get.getTile(x, y + yy, z); - return state.toBaseBlock(tag); + final FaweCompoundTag tag = get.tile(x, y + yy, z); + return state.toBaseBlock(tag == null ? null : tag.linTag()); } return state.toBaseBlock(); } @@ -268,16 +272,28 @@ public class CharFilterBlock extends ChunkFilterBlock { @Override public void setFullBlock(BaseBlock block) { delegate.set(this, block.getOrdinalChar()); - final CompoundTag nbt = block.getNbtData(); + final LazyReference nbt = block.getNbtReference(); if (nbt != null) { // TODO optimize check via ImmutableBaseBlock - set.setTile(x, yy + y, z, nbt); + set.tile(x, yy + y, z, FaweCompoundTag.of(nbt)); } } @Override - public final CompoundTag getNbtData() { - return get.getTile(x, y + yy, z); + public @Nullable LinCompoundTag getNbt() { + final FaweCompoundTag tile = get.tile(x, y + yy, z); + if (tile == null) { + return null; + } + return tile.linTag(); } + + @Override + public void setNbt(@Nullable final LinCompoundTag nbtData) { + if (nbtData != null) { + set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData)); + } + } + /* NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1), EAST(Vector3.at(1, 0, 0), Flag.CARDINAL, 0, 2), @@ -286,9 +302,9 @@ public class CharFilterBlock extends ChunkFilterBlock { */ @Override - public void setNbtData(CompoundTag tag) { - if (tag != null) { - set.setTile(x, y + yy, z, tag); + public void setNbtReference(@Nullable final LazyReference nbtData) { + if (nbtData != null) { + set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData)); } } @@ -304,7 +320,7 @@ public class CharFilterBlock extends ChunkFilterBlock { if (z > 0) { return states[getArr[index - 16]]; } - return getExtent().getBlock(getX(), getY(), getZ() - 1); + return getExtent().getBlock(x(), y(), z() - 1); } @Override @@ -312,7 +328,7 @@ public class CharFilterBlock extends ChunkFilterBlock { if (x < 15) { return states[getArr[index + 1]]; } - return getExtent().getBlock(getX() + 1, getY(), getZ()); + return getExtent().getBlock(x() + 1, y(), z()); } @Override @@ -320,7 +336,7 @@ public class CharFilterBlock extends ChunkFilterBlock { if (z < 15) { return states[getArr[index + 16]]; } - return getExtent().getBlock(getX(), getY(), getZ() + 1); + return getExtent().getBlock(x(), y(), z() + 1); } @Override @@ -328,7 +344,7 @@ public class CharFilterBlock extends ChunkFilterBlock { if (x > 0) { return states[getArr[index - 1]]; } - return getExtent().getBlock(getX() - 1, getY(), getZ()); + return getExtent().getBlock(x() - 1, y(), z()); } @Override @@ -380,7 +396,7 @@ public class CharFilterBlock extends ChunkFilterBlock { } //Set delegate - private SetDelegate initSet() { + protected final SetDelegate initSet() { setArr = set.load(layer); return delegate = FULL; } @@ -401,7 +417,7 @@ public class CharFilterBlock extends ChunkFilterBlock { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getBlockZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override @@ -412,7 +428,8 @@ public class CharFilterBlock extends ChunkFilterBlock { return getExtent().setBiome(x, y, z, biome); } - private interface SetDelegate { + @ApiStatus.Internal + protected interface SetDelegate { void set(@Nonnull CharFilterBlock block, char value); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java index 9e11021d2..830ff9ab1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java @@ -83,12 +83,20 @@ public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock { /** * Filter a chunk with a region / filter. */ - public synchronized final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter, Region region, boolean full) { + public synchronized final IChunkSet filter( + IChunk chunk, + IChunkGet get, + IChunkSet set, + Filter filter, + Region region, + boolean full + ) { if (region != null) { region.filter(chunk, filter, this, get, set, full); } else { for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { continue; } initLayer(get, set, layer); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java index c27d3770a..c35f549a2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.extent.filter.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.TileEntityBlock; @@ -35,17 +36,6 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn public abstract BiomeType getBiome(); - @Override - public abstract CompoundTag getNbtData(); - - @Override - public abstract void setNbtData(@Nullable CompoundTag nbtData); - - @Override - public boolean hasNbtData() { - return getNbtData() != null; - } - @Override public BlockVector3 getMinimumPoint() { return getExtent().getMinimumPoint(); @@ -61,10 +51,9 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn return getExtent().getBlock(x, y, z); } - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return getExtent().setTile(x, y, z, tile); + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + return getExtent().tile(x, y, z, tile); } @Override @@ -73,60 +62,60 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn } public BlockState getBlockBelow() { - return getBlock(getX(), getY() - 1, getZ()); + return getBlock(x(), y() - 1, z()); } public BlockState getBlockAbove() { - return getBlock(getX(), getY() + 1, getZ()); + return getBlock(x(), y() + 1, z()); } public BlockState getBlockNorth() { - return getBlock(getX(), getY(), getZ() - 1); + return getBlock(x(), y(), z() - 1); } public BlockState getBlockEast() { - return getBlock(getX() + 1, getY(), getZ()); + return getBlock(x() + 1, y(), z()); } public BlockState getBlockSouth() { - return getBlock(getX(), getY(), getZ() + 1); + return getBlock(x(), y(), z() + 1); } public BlockState getBlockWest() { - return getBlock(getX() - 1, getY(), getZ()); + return getBlock(x() - 1, y(), z()); } public BlockState getBlockRelativeY(int y) { - return getBlock(getX(), getY() + y, getZ()); + return getBlock(x(), y() + y, z()); } @Override - public abstract int getX(); + public abstract int x(); @Override - public abstract int getY(); + public abstract int y(); @Override - public abstract int getZ(); + public abstract int z(); public int getLocalX() { - return getX() & 15; + return x() & 15; } public int getLocalY() { - return getY() & 15; + return y() & 15; } public int getLocalZ() { - return getZ() & 15; + return z() & 15; } public int getChunkX() { - return getX() >> 4; + return x() >> 4; } public int getChunkZ() { - return getZ() >> 4; + return z() >> 4; } /* @@ -204,7 +193,7 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/SingleFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/SingleFilterBlock.java index 5516ae3bb..83301c4ea 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/SingleFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/SingleFilterBlock.java @@ -17,17 +17,17 @@ public class SingleFilterBlock extends AbstractSingleFilterBlock { } @Override - public int getX() { + public int x() { return x; } @Override - public int getY() { + public int y() { return y; } @Override - public int getZ() { + public int z() { return z; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/EntityInBlockRemovingProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/EntityInBlockRemovingProcessor.java index 58baf8633..693356a7a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/EntityInBlockRemovingProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/EntityInBlockRemovingProcessor.java @@ -30,9 +30,9 @@ public class EntityInBlockRemovingProcessor implements IBatchProcessor { continue; } BlockVector3 pos = tag.getEntityPosition().toBlockPoint(); - int x = pos.getX() & 15; - int y = pos.getY(); - int z = pos.getZ() & 15; + int x = pos.x() & 15; + int y = pos.y(); + int z = pos.z() & 15; if (!set.hasSection(y >> 4)) { continue; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/MultiBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/MultiBatchProcessor.java index e57ccb490..c266fd544 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/MultiBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/MultiBatchProcessor.java @@ -19,12 +19,9 @@ import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.function.Supplier; @@ -80,28 +77,18 @@ public class MultiBatchProcessor implements IBatchProcessor { @Override public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { - Map> ordered = new HashMap<>(); + Map> ordered = new HashMap<>(); IChunkSet chunkSet = set; for (IBatchProcessor processor : processors) { if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) { - ordered.merge( - processor.getScope().intValue(), - new HashSet<>(Collections.singleton(processor)), - (existing, theNew) -> { - existing.add(processor); - return existing; - } - ); + ordered.computeIfAbsent(processor.getScope().intValue(), k -> new ArrayList<>()) + .add(processor); continue; } chunkSet = processSet(processor, chunk, get, chunkSet); } - if (ordered.size() > 0) { - for (int i = 1; i <= 4; i++) { - Set processors = ordered.get(i); - if (processors == null) { - continue; - } + if (!ordered.isEmpty()) { + for (List processors : ordered.values()) { for (IBatchProcessor processor : processors) { chunkSet = processSet(processor, chunk, get, chunkSet); if (chunkSet == null) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightMapType.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightMapType.java index d49644f24..cb5339737 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightMapType.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightMapType.java @@ -17,19 +17,19 @@ public enum HeightMapType { MOTION_BLOCKING { @Override public boolean includes(BlockState state) { - return state.getMaterial().isSolid() || HeightMapType.hasFluid(state); + return state.getMaterial().isMovementBlocker() || HeightMapType.hasFluid(state); } }, MOTION_BLOCKING_NO_LEAVES { @Override public boolean includes(BlockState state) { - return (state.getMaterial().isSolid() || HeightMapType.hasFluid(state)) && !HeightMapType.isLeaf(state); + return (state.getMaterial().isMovementBlocker() || HeightMapType.hasFluid(state)) && !HeightMapType.isLeaf(state); } }, OCEAN_FLOOR { @Override public boolean includes(BlockState state) { - return state.getMaterial().isSolid(); + return state.getMaterial().isMovementBlocker(); } }, WORLD_SURFACE { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java index 3cdfeafb9..5d8f81e39 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java @@ -12,8 +12,6 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; public class HeightmapProcessor implements IBatchProcessor { @@ -25,7 +23,7 @@ public class HeightmapProcessor implements IBatchProcessor { static { Arrays.fill(COMPLETE, true); - Arrays.fill(AIR_LAYER, (char) 1); + Arrays.fill(AIR_LAYER, (char) BlockTypesCache.ReservedIDs.AIR); } private final int minY; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java index 97a97f9a7..2ad473130 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java @@ -4,7 +4,6 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.math.BlockVectorSet; import com.fastasyncworldedit.core.math.MutableBlockVector3; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkHolder; import com.fastasyncworldedit.core.util.MathMan; @@ -34,7 +33,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; -@SuppressWarnings("rawtypes") public class NMSRelighter implements Relighter { private static final int DISPATCH_SIZE = 64; @@ -51,7 +49,7 @@ public class NMSRelighter implements Relighter { } public final MutableBlockVector3 mutableBlockPos = new MutableBlockVector3(0, 0, 0); - private final IQueueExtent queue; + private final IQueueExtent queue; private final Map skyToRelight; private final Object present = new Object(); private final Map chunksToSend; @@ -66,11 +64,11 @@ public class NMSRelighter implements Relighter { private final AtomicBoolean finished = new AtomicBoolean(false); private boolean removeFirst; - public NMSRelighter(IQueueExtent queue) { + public NMSRelighter(IQueueExtent queue) { this(queue, null); } - public NMSRelighter(IQueueExtent queue, RelightMode relightMode) { + public NMSRelighter(IQueueExtent queue, RelightMode relightMode) { this.queue = queue; this.skyToRelight = new Long2ObjectOpenHashMap<>(12); this.lightQueue = new Long2ObjectOpenHashMap<>(12); @@ -275,9 +273,9 @@ public class NMSRelighter implements Relighter { int lightLevel = (int) val[1]; this.computeRemoveBlockLight( - node.getX() - 1, - node.getY(), - node.getZ(), + node.x() - 1, + node.y(), + node.z(), lightLevel, lightRemovalQueue, lightPropagationQueue, @@ -285,20 +283,20 @@ public class NMSRelighter implements Relighter { visited ); this.computeRemoveBlockLight( - node.getX() + 1, - node.getY(), - node.getZ(), + node.x() + 1, + node.y(), + node.z(), lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited ); - if (node.getY() > minY) { + if (node.y() > minY) { this.computeRemoveBlockLight( - node.getX(), - node.getY() - 1, - node.getZ(), + node.x(), + node.y() - 1, + node.z(), lightLevel, lightRemovalQueue, lightPropagationQueue, @@ -306,11 +304,11 @@ public class NMSRelighter implements Relighter { visited ); } - if (node.getY() < maxY) { + if (node.y() < maxY) { this.computeRemoveBlockLight( - node.getX(), - node.getY() + 1, - node.getZ(), + node.x(), + node.y() + 1, + node.z(), lightLevel, lightRemovalQueue, lightPropagationQueue, @@ -319,9 +317,9 @@ public class NMSRelighter implements Relighter { ); } this.computeRemoveBlockLight( - node.getX(), - node.getY(), - node.getZ() - 1, + node.x(), + node.y(), + node.z() - 1, lightLevel, lightRemovalQueue, lightPropagationQueue, @@ -329,9 +327,9 @@ public class NMSRelighter implements Relighter { visited ); this.computeRemoveBlockLight( - node.getX(), - node.getY(), - node.getZ() + 1, + node.x(), + node.y(), + node.z() + 1, lightLevel, lightRemovalQueue, lightPropagationQueue, @@ -342,27 +340,27 @@ public class NMSRelighter implements Relighter { while (!lightPropagationQueue.isEmpty()) { MutableBlockVector3 node = lightPropagationQueue.poll(); - ChunkHolder iChunk = (ChunkHolder) queue.getOrCreateChunk(node.getX() >> 4, node.getZ() >> 4); + ChunkHolder iChunk = (ChunkHolder) queue.getOrCreateChunk(node.x() >> 4, node.z() >> 4); if (!iChunk.isInit()) { - iChunk.init(queue, node.getX() >> 4, node.getZ() >> 4); + iChunk.init(queue, node.x() >> 4, node.z() >> 4); } - int lightLevel = iChunk.getEmittedLight(node.getX() & 15, node.getY(), node.getZ() & 15); - BlockState state = this.queue.getBlock(node.getX(), node.getY(), node.getZ()); - String id = state.getBlockType().getId().toLowerCase(Locale.ROOT); + int lightLevel = iChunk.getEmittedLight(node.x() & 15, node.y(), node.z() & 15); + BlockState state = this.queue.getBlock(node.x(), node.y(), node.z()); + String id = state.getBlockType().id().toLowerCase(Locale.ROOT); if (lightLevel <= 1) { continue; } if (id.contains("slab")) { boolean top = state.getState(slabHalf).equalsIgnoreCase("top"); - computeSlab(node.getX(), node.getY(), node.getZ(), lightLevel, lightPropagationQueue, visited, top); + computeSlab(node.x(), node.y(), node.z(), lightLevel, lightPropagationQueue, visited, top); } else if (id.contains("stair")) { boolean top = state.getState(stairHalf).equalsIgnoreCase("top"); Direction direction = getStairDir(state); String shape = getStairShape(state); computeStair( - node.getX(), - node.getY(), - node.getZ(), + node.x(), + node.y(), + node.z(), lightLevel, lightPropagationQueue, visited, @@ -371,7 +369,7 @@ public class NMSRelighter implements Relighter { shape ); } else { - computeNormal(node.getX(), node.getY(), node.getZ(), lightLevel, lightPropagationQueue, visited); + computeNormal(node.x(), node.y(), node.z(), lightLevel, lightPropagationQueue, visited); } } } @@ -398,7 +396,7 @@ public class NMSRelighter implements Relighter { if (!(checkStairEast(state) && isStairOrTrueTop(state, top) && isSlabOrTrueValue(state, top ? "top" : "bottom"))) { break east; } - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { this.computeSpreadBlockLight(x + 1, y, z, currentLight, queue, visited); break east; } @@ -451,7 +449,7 @@ public class NMSRelighter implements Relighter { if (!(checkStairWest(state) && isStairOrTrueTop(state, top) && isSlabOrTrueValue(state, top ? "top" : "bottom"))) { break west; } - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { this.computeSpreadBlockLight(x - 1, y, z, currentLight, queue, visited); break west; } @@ -504,7 +502,7 @@ public class NMSRelighter implements Relighter { if (!(checkStairSouth(state) && isStairOrTrueTop(state, top) && isSlabOrTrueValue(state, top ? "top" : "bottom"))) { break south; } - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { this.computeSpreadBlockLight(x, y, z + 1, currentLight, queue, visited); break south; } @@ -557,7 +555,7 @@ public class NMSRelighter implements Relighter { if (!(checkStairNorth(state) && isStairOrTrueTop(state, top) && isSlabOrTrueValue(state, top ? "top" : "bottom"))) { break north; } - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { this.computeSpreadBlockLight(x, y, z - 1, currentLight, queue, visited); break north; } @@ -709,7 +707,7 @@ public class NMSRelighter implements Relighter { } private boolean checkStairNorth(BlockState state) { - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { return true; } Direction direction = getStairDir(state); @@ -727,7 +725,7 @@ public class NMSRelighter implements Relighter { } private boolean checkStairSouth(BlockState state) { - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { return true; } Direction direction = getStairDir(state); @@ -745,7 +743,7 @@ public class NMSRelighter implements Relighter { } private boolean checkStairEast(BlockState state) { - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { return true; } Direction direction = getStairDir(state); @@ -763,7 +761,7 @@ public class NMSRelighter implements Relighter { } private boolean checkStairWest(BlockState state) { - if (!state.getBlockType().getId().toLowerCase(Locale.ROOT).contains("stair")) { + if (!state.getBlockType().id().toLowerCase(Locale.ROOT).contains("stair")) { return true; } Direction direction = getStairDir(state); @@ -789,11 +787,11 @@ public class NMSRelighter implements Relighter { } private boolean isStairOrTrueTop(BlockState state, boolean top) { - return !state.getBlockType().getId().contains("stair") || state.getState(stairHalf).equals("top") == top; + return !state.getBlockType().id().contains("stair") || state.getState(stairHalf).equals("top") == top; } private boolean isSlabOrTrueValue(BlockState state, String value) { - return !state.getBlockType().getId().contains("slab") || state.getState(slabHalf).equals(value); + return !state.getBlockType().id().contains("slab") || state.getState(slabHalf).equals(value); } private void computeRemoveBlockLight( diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/RelighterFactory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/RelighterFactory.java index 34275f77d..f0bca36ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/RelighterFactory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/RelighterFactory.java @@ -1,6 +1,5 @@ package com.fastasyncworldedit.core.extent.processor.lighting; -import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; @@ -25,6 +24,6 @@ public interface RelighterFactory { * @return a new Relighter instance with the specified settings. */ @Nonnull - Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue); + Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent queue); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/OffsetTransform.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/OffsetTransform.java index a8ade6df1..c2536deca 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/OffsetTransform.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/OffsetTransform.java @@ -30,9 +30,9 @@ public class OffsetTransform extends ResettableExtent { @Override public boolean setBiome(BlockVector3 location, BiomeType biome) { - int x = location.getX() + dx; - int y = location.getX() + dy; - int z = location.getX() + dz; + int x = location.x() + dx; + int y = location.x() + dy; + int z = location.x() + dz; if (!getExtent().contains(x, y, z)) { return false; } @@ -53,9 +53,9 @@ public class OffsetTransform extends ResettableExtent { @Override public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - int x = location.getX() + dx; - int y = location.getX() + dy; - int z = location.getX() + dz; + int x = location.x() + dx; + int y = location.x() + dy; + int z = location.x() + dz; if (!getExtent().contains(x, y, z)) { return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomOffsetTransform.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomOffsetTransform.java index 268255bf2..4ad3189c7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomOffsetTransform.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomOffsetTransform.java @@ -34,9 +34,9 @@ public class RandomOffsetTransform extends ResettableExtent { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - int x = position.getBlockX() + random.nextInt(1 + (dx << 1)) - dx; - int y = position.getBlockY() + random.nextInt(1 + (dy << 1)) - dy; - int z = position.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz; + int x = position.x() + random.nextInt(1 + (dx << 1)) - dx; + int y = position.y() + random.nextInt(1 + (dy << 1)) - dy; + int z = position.z() + random.nextInt(1 + (dz << 1)) - dz; if (!getExtent().contains(x, y, z)) { return false; } @@ -57,9 +57,9 @@ public class RandomOffsetTransform extends ResettableExtent { @Override public > boolean setBlock(BlockVector3 pos, T block) throws WorldEditException { - int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx; - int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy; - int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz; + int x = pos.x() + random.nextInt(1 + (dx << 1)) - dx; + int y = pos.y() + random.nextInt(1 + (dy << 1)) - dy; + int z = pos.z() + random.nextInt(1 + (dz << 1)) - dz; if (!getExtent().contains(x, y, z)) { return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/ScaleTransform.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/ScaleTransform.java index 29af87055..c81d123df 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/ScaleTransform.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/ScaleTransform.java @@ -55,9 +55,9 @@ public class ScaleTransform extends ResettableExtent { if (min == null) { min = pos; } - mutable.mutX(min.getX() + (pos.getX() - min.getX()) * dx); - mutable.mutY(min.getY() + (pos.getY() - min.getY()) * dy); - mutable.mutZ(min.getZ() + (pos.getZ() - min.getZ()) * dz); + mutable.mutX(min.x() + (pos.x() - min.x()) * dx); + mutable.mutY(min.y() + (pos.y() - min.y()) * dy); + mutable.mutZ(min.z() + (pos.z() - min.z()) * dz); return new MutableVector3(mutable); } @@ -65,9 +65,9 @@ public class ScaleTransform extends ResettableExtent { if (min == null) { min = BlockVector3.at(x, y, z); } - mutable.mutX(min.getX() + (x - min.getX()) * dx); - mutable.mutY(min.getY() + (y - min.getY()) * dy); - mutable.mutZ(min.getZ() + (z - min.getZ()) * dz); + mutable.mutX(min.x() + (x - min.x()) * dx); + mutable.mutY(min.y() + (y - min.y()) * dy); + mutable.mutZ(min.z() + (z - min.z()) * dz); return new MutableVector3(mutable); } @@ -77,15 +77,15 @@ public class ScaleTransform extends ResettableExtent { boolean result = false; MutableVector3 vector3 = getPos(location); MutableBlockVector3 pos = new MutableBlockVector3(); - double sx = vector3.getX(); - double sy = vector3.getY(); - double sz = vector3.getZ(); + double sx = vector3.x(); + double sy = vector3.y(); + double sz = vector3.z(); double ex = sx + dx; double ey = Math.max(minY, Math.min(maxy, sy + dy)); double ez = sz + dz; - for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) { - for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { - for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { + for (pos.mutY(sy); pos.y() < ey; pos.mutY(pos.y() + 1)) { + for (pos.mutZ(sz); pos.z() < ez; pos.mutZ(pos.z() + 1)) { + for (pos.mutX(sx); pos.x() < ex; pos.mutX(pos.x() + 1)) { if (!getExtent().contains(pos)) { continue; } @@ -101,15 +101,15 @@ public class ScaleTransform extends ResettableExtent { boolean result = false; MutableVector3 vector3 = getPos(position); MutableBlockVector3 pos = new MutableBlockVector3(); - double sx = vector3.getX(); - double sy = vector3.getY(); - double sz = vector3.getZ(); + double sx = vector3.x(); + double sy = vector3.y(); + double sz = vector3.z(); double ex = sx + dx; double ey = Math.max(minY, Math.min(maxy, sy + dy)); double ez = sz + dz; - for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) { - for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { - for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { + for (pos.mutY(sy); pos.y() < ey; pos.mutY(pos.y() + 1)) { + for (pos.mutZ(sz); pos.z() < ez; pos.mutZ(pos.z() + 1)) { + for (pos.mutX(sx); pos.x() < ex; pos.mutX(pos.x() + 1)) { if (!getExtent().contains(pos)) { continue; } @@ -126,15 +126,15 @@ public class ScaleTransform extends ResettableExtent { boolean result = false; MutableVector3 vector3 = getPos(x1, y1, z1); MutableBlockVector3 pos = new MutableBlockVector3(); - double sx = vector3.getX(); - double sy = vector3.getY(); - double sz = vector3.getZ(); - double ex = vector3.getX() + dx; + double sx = vector3.x(); + double sy = vector3.y(); + double sz = vector3.z(); + double ex = vector3.x() + dx; double ey = Math.min(maxy, sy + dy); - double ez = vector3.getZ() + dz; - for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) { - for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { - for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { + double ez = vector3.z() + dz; + for (pos.mutY(sy); pos.y() < ey; pos.mutY(pos.y() + 1)) { + for (pos.mutZ(sz); pos.z() < ez; pos.mutZ(pos.z() + 1)) { + for (pos.mutX(sx); pos.x() < ex; pos.mutX(pos.x() + 1)) { if (!getExtent().contains(pos)) { continue; } @@ -150,15 +150,15 @@ public class ScaleTransform extends ResettableExtent { boolean result = false; MutableVector3 vector3 = getPos(x1, y1, z1); MutableBlockVector3 pos = new MutableBlockVector3(); - double sx = vector3.getX(); - double sy = vector3.getY(); - double sz = vector3.getZ(); + double sx = vector3.x(); + double sy = vector3.y(); + double sz = vector3.z(); double ex = sx + dx; double ey = Math.max(minY, Math.min(maxy, sy + dy)); double ez = sz + dz; - for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) { - for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { - for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { + for (pos.mutY(sy); pos.y() < ey; pos.mutY(pos.y() + 1)) { + for (pos.mutZ(sz); pos.z() < ez; pos.mutZ(pos.z() + 1)) { + for (pos.mutX(sx); pos.x() < ex; pos.mutX(pos.x() + 1)) { if (!getExtent().contains(pos)) { continue; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/SelectTransform.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/SelectTransform.java index 57f77b2fe..b3be0a43a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/SelectTransform.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/SelectTransform.java @@ -27,11 +27,11 @@ public abstract class SelectTransform extends ResettableExtent { public abstract AbstractDelegateExtent getExtent(int x, int z); public Extent getExtent(BlockVector3 pos) { - return getExtent(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); + return getExtent(pos.x(), pos.y(), pos.z()); } public Extent getExtent(BlockVector2 pos) { - return getExtent(pos.getBlockX(), pos.getBlockZ()); + return getExtent(pos.x(), pos.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/SurfaceRegionFunction.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/SurfaceRegionFunction.java index 5f946c933..a6b9ace56 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/SurfaceRegionFunction.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/SurfaceRegionFunction.java @@ -26,8 +26,8 @@ public class SurfaceRegionFunction implements FlatRegionFunction { @Override public boolean apply(BlockVector2 position) throws WorldEditException { - int x = position.getBlockX(); - int z = position.getBlockZ(); + int x = position.x(); + int z = position.z(); int layer = extent.getNearestSurfaceTerrainBlock(x, z, lastY, minY, maxY, false); if (layer != -1) { lastY = layer; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/block/BiomeCopy.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/block/BiomeCopy.java index 3926c19a6..457fff477 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/block/BiomeCopy.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/block/BiomeCopy.java @@ -21,11 +21,11 @@ public class BiomeCopy implements RegionFunction { @Override public boolean apply(BlockVector3 position) throws WorldEditException { - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - if (x != mutableVector.getBlockX() || z != mutableVector.getBlockZ() || y != mutableVector - .getBlockY()) { + int x = position.x(); + int y = position.y(); + int z = position.z(); + if (x != mutableVector.x() || z != mutableVector.z() || y != mutableVector + .y()) { mutableVector.setComponents(x, y, z); return destination.setBiome(mutableVector, source.getBiome(mutableVector)); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/CavesGen.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/CavesGen.java index 28bfa0a4c..7e4b61514 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/CavesGen.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/CavesGen.java @@ -72,8 +72,8 @@ public class CavesGen extends GenBase { int maxAngle, double paramDouble4 ) throws WorldEditException { - int bx = chunkPos.getBlockX() << 4; - int bz = chunkPos.getBlockZ() << 4; + int bx = chunkPos.x() << 4; + int bz = chunkPos.z() << 4; double real_x = bx + 7; double real_z = bz + 7; @@ -236,7 +236,7 @@ public class CavesGen extends GenBase { BlockState material = chunk.getBlock(bx + local_x, local_y, bz + local_z); BlockState materialAbove = chunk.getBlock(bx + local_x, local_y + 1, bz + local_z); BlockType blockType = material.getBlockType(); - switch (blockType.getId()) { + switch (blockType.id()) { case "minecraft:mycelium", "minecraft:grass_block" -> grassFound = true; } if (this.isSuitableBlock(material, materialAbove)) { @@ -277,7 +277,7 @@ public class CavesGen extends GenBase { } protected boolean isSuitableBlock(BlockStateHolder material, BlockStateHolder materialAbove) { - return switch (material.getBlockType().getId()) { + return switch (material.getBlockType().id()) { case "minecraft:air", "minecraft:cave_air", "minecraft:void_air", "minecraft:water", "minecraft:lava", "minecraft:bedrock" -> false; default -> true; }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/GenBase.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/GenBase.java index af1a4e66e..f0637d127 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/GenBase.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/GenBase.java @@ -26,8 +26,8 @@ public abstract class GenBase { public void generate(BlockVector2 chunkPos, Extent chunk) throws WorldEditException { int i = this.checkAreaSize; - int chunkX = chunkPos.getBlockX(); - int chunkZ = chunkPos.getBlockZ(); + int chunkX = chunkPos.x(); + int chunkZ = chunkPos.z(); for (int x = chunkX - i; x <= chunkX + i; x++) { for (int z = chunkZ - i; z <= chunkZ + i; z++) { generateChunk(x, z, chunkPos, chunk); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/SchemGen.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/SchemGen.java index 1ced63f19..775e9cf4c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/SchemGen.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/generator/SchemGen.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; import java.util.List; @@ -19,29 +20,60 @@ public class SchemGen implements Resource { private final List clipboards; private final boolean randomRotate; private final Mask mask; + private final Region region; private final MutableBlockVector3 mutable = new MutableBlockVector3(); + /** + * @deprecated Use {@link SchemGen#SchemGen(Mask, Extent, List, boolean, Region)} + */ + @Deprecated(forRemoval = true, since = "2.11.1") public SchemGen(Mask mask, Extent extent, List clipboards, boolean randomRotate) { this.mask = mask; this.extent = extent; this.clipboards = clipboards; this.randomRotate = randomRotate; + this.region = null; + } + + /** + * New instance. Places a schematic on terrain at a given x,z when appropriate + * + * @since 2.11.1 + */ + public SchemGen(Mask mask, Extent extent, List clipboards, boolean randomRotate, Region region) { + this.mask = mask; + this.extent = extent; + this.clipboards = clipboards; + this.randomRotate = randomRotate; + this.region = region; + } + + private int getY(int x, int z) { + if (region == null) { + return extent.getNearestSurfaceTerrainBlock( + x, + z, + mutable.y(), + this.extent.getMinY(), + this.extent.getMaxY(), + Integer.MIN_VALUE, + Integer.MAX_VALUE + ); + } else { + int y = extent.getHighestTerrainBlock(x, z, region.getMinimumY(), region.getMaximumY(), mask); + if (y == region.getMinimumY() && !extent.getBlock(x, y, z).getMaterial().isMovementBlocker()) { + return Integer.MIN_VALUE; + } + return y; + } } @Override public boolean spawn(Random random, int x, int z) throws WorldEditException { mutable.mutX(x); mutable.mutZ(z); - int y = extent.getNearestSurfaceTerrainBlock( - x, - z, - mutable.getBlockY(), - this.extent.getMinY(), - this.extent.getMaxY(), - Integer.MIN_VALUE, - Integer.MAX_VALUE - ); + int y = getY(x, z); if (y == Integer.MIN_VALUE || y == Integer.MAX_VALUE) { return false; } @@ -54,7 +86,8 @@ public class SchemGen implements Resource { if (randomRotate) { holder.setTransform(new AffineTransform().rotateY(ThreadLocalRandom.current().nextInt(4) * 90)); } - Clipboard clipboard = holder.getClipboard(); + Clipboard clipboard = holder.getClipboards().size() == 1 ? holder.getClipboard() : + holder.getClipboards().get(ThreadLocalRandom.current().nextInt(clipboards.size())); Transform transform = holder.getTransform(); if (transform.isIdentity()) { clipboard.paste(extent, mutable, false); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java index 1f0b88bfa..ed5b028dd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java @@ -26,7 +26,7 @@ public abstract class ABlockMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector)); + return test(vector.getBlock(getExtent())); } public abstract boolean test(BlockState state); @@ -40,7 +40,7 @@ public abstract class ABlockMask extends AbstractExtentMask { List all = type.getAllStates(); hasAll = all.stream().map(this::test).reduce(true, (a, b) -> a && b); if (hasAll) { - strings.add(type.getId()); + strings.add(type.id()); } else { for (BlockState state : all) { if (test(state)) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentAnyMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentAnyMask.java index 39bb0c41d..956daf67d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentAnyMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentAnyMask.java @@ -44,9 +44,9 @@ public class AdjacentAnyMask extends AbstractMask implements ResettableMask { } public BlockVector3 direction(BlockVector3 v) { - int x = v.getBlockX(); - int y = v.getBlockY(); - int z = v.getBlockZ(); + int x = v.x(); + int y = v.y(); + int z = v.z(); if (mask.test(mutable.setComponents(x + 1, y, z))) { return mutable.setComponents(1, 0, 0); } else if (mask.test(mutable.setComponents(x - 1, y, z))) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentMask.java index 23065ea7b..981492e0e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AdjacentMask.java @@ -22,9 +22,9 @@ public class AdjacentMask extends AbstractMask { @Override public boolean test(BlockVector3 bv) { vector.setComponents(bv); - double x = bv.getX(); - double y = bv.getY(); - double z = bv.getZ(); + double x = bv.x(); + double y = bv.y(); + double z = bv.z(); vector.mutX(x + 1); int count = 0; if (mask.test(vector) && ++count == min && max >= 8) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AngleMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AngleMask.java index 52de762ae..01cf15708 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AngleMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/AngleMask.java @@ -127,9 +127,9 @@ public class AngleMask extends AbstractExtentMask implements ResettableMask { } private boolean adjacentAir(Extent extent, MutableBlockVector3 mutable) { - int x = mutable.getBlockX(); - int y = mutable.getBlockY(); - int z = mutable.getBlockZ(); + int x = mutable.x(); + int y = mutable.y(); + int z = mutable.z(); if (!mask.test(extent, mutable.setComponents(x + 1, y, z))) { return true; } @@ -154,23 +154,23 @@ public class AngleMask extends AbstractExtentMask implements ResettableMask { if (!mask.test(vector)) { return false; } - int y = vector.getBlockY(); + int y = vector.y(); if (overlay) { MutableBlockVector3 mutable = new MutableBlockVector3(vector); if (y < maxY && !adjacentAir(null, mutable)) { return false; } } - int x = vector.getBlockX(); - int z = vector.getBlockZ(); + int x = vector.x(); + int z = vector.z(); return testSlope(getExtent(), x, y, z); } @Override public boolean test(final Extent extent, final BlockVector3 vector) { - int x = vector.getBlockX(); - int y = vector.getBlockY(); - int z = vector.getBlockZ(); + int x = vector.x(); + int y = vector.y(); + int z = vector.z(); if ((lastX == (lastX = x) & lastZ == (lastZ = z))) { int height = getHeight(extent, x, y, z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/BlockMaskBuilder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/BlockMaskBuilder.java index 2471ff262..7ca60bdd1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/BlockMaskBuilder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/BlockMaskBuilder.java @@ -9,6 +9,7 @@ import com.fastasyncworldedit.core.util.MutableCharSequence; import com.fastasyncworldedit.core.util.StringMan; import com.fastasyncworldedit.core.world.block.BlanketBaseBlock; import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.registry.state.AbstractProperty; @@ -53,6 +54,7 @@ public class BlockMaskBuilder { private static final long[] ALL = new long[0]; private final long[][] bitSets; + private final ParserContext context; private boolean[] ordinals; private boolean optimizedStates = true; @@ -60,8 +62,28 @@ public class BlockMaskBuilder { this(new long[BlockTypes.size()][]); } + /** + * Create a new instance with a given {@link ParserContext} to use if parsing regex + * + * @since 2.11.0 + */ + public BlockMaskBuilder(ParserContext context) { + this(new long[BlockTypes.size()][], context); + } + protected BlockMaskBuilder(long[][] bitSets) { this.bitSets = bitSets; + this.context = new ParserContext(); + } + + /** + * Create a new instance with a given {@link ParserContext} to use if parsing regex + * + * @since 2.11.0 + */ + protected BlockMaskBuilder(long[][] bitSets, ParserContext context) { + this.bitSets = bitSets; + this.context = context; } private boolean handleRegex(BlockType blockType, PropertyKey key, String regex, FuzzyStateAllowingBuilder builder) { @@ -173,7 +195,7 @@ public class BlockMaskBuilder { List blockTypeList; List builders; if (StringMan.isAlphanumericUnd(charSequence)) { - BlockType type = BlockTypes.parse(charSequence.toString()); + BlockType type = BlockTypes.parse(charSequence.toString(), context); blockTypeList = Collections.singletonList(type); builders = Collections.singletonList(new FuzzyStateAllowingBuilder(type)); add(type); @@ -183,7 +205,7 @@ public class BlockMaskBuilder { builders = new ArrayList<>(); Pattern pattern = Pattern.compile("(minecraft:)?" + regex); for (BlockType type : BlockTypesCache.values) { - if (pattern.matcher(type.getId()).find()) { + if (pattern.matcher(type.id()).find()) { blockTypeList.add(type); builders.add(new FuzzyStateAllowingBuilder(type)); add(type); @@ -280,11 +302,11 @@ public class BlockMaskBuilder { } } else { if (StringMan.isAlphanumericUnd(input)) { - add(BlockTypes.parse(input)); + add(BlockTypes.parse(input, context)); } else { boolean success = false; for (BlockType myType : BlockTypesCache.values) { - if (myType.getId().matches("(minecraft:)?" + input)) { + if (myType.id().matches("(minecraft:)?" + input)) { add(myType); success = true; } @@ -571,7 +593,7 @@ public class BlockMaskBuilder { throw new IllegalArgumentException(String.format( "Property %s cannot be applied to block type %s", property.getName(), - type.getId() + type.id() )); } masked.computeIfAbsent(property, k -> new ArrayList<>()).add(index); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/CachedMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/CachedMask.java index 27e4b9961..5bb757eb2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/CachedMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/CachedMask.java @@ -60,9 +60,9 @@ public class CachedMask extends AbstractDelegateMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { - int x = vector.getX(); - int y = vector.getY(); - int z = vector.getZ(); + int x = vector.x(); + int y = vector.y(); + int z = vector.z(); try { boolean check = cache_checked.add(x, y, z); if (!check) { @@ -88,9 +88,9 @@ public class CachedMask extends AbstractDelegateMask implements ResettableMask { if (!hasExtent || !(extent instanceof AbstractExtentMask)) { return test(vector); } - int x = vector.getX(); - int y = vector.getY(); - int z = vector.getZ(); + int x = vector.x(); + int y = vector.y(); + int z = vector.z(); AbstractExtentMask mask = (AbstractExtentMask) getMask(); try { boolean check = cache_checked.add(x, y, z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java index 2b3ad7edb..84b8f77ad 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java @@ -16,9 +16,9 @@ public class DataMask extends AbstractExtentMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { if (data != -1) { - return getExtent().getBlock(vector).getInternalPropertiesId() == data; + return vector.getBlock(getExtent()).getInternalPropertiesId() == data; } else { - data = getExtent().getBlock(vector).getInternalPropertiesId(); + data = vector.getBlock(getExtent()).getInternalPropertiesId(); return true; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java index 49c90183a..b0ba4fb59 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java @@ -24,7 +24,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { - return test(getExtent(), vector); + int blockID = vector.getBlock(getExtent()).getInternalBlockTypeId(); + int testId = id.compareAndExchange(-1, blockID); + return blockID == testId || testId == -1; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ImageBrushMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ImageBrushMask.java index ec31337de..d8ff64a76 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ImageBrushMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ImageBrushMask.java @@ -62,17 +62,17 @@ public class ImageBrushMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { if (solid.test(vector)) { - int dx = vector.getBlockX() - center.getBlockX(); - int dy = vector.getBlockY() - center.getBlockY(); - int dz = vector.getBlockZ() - center.getBlockZ(); + int dx = vector.x() - center.x(); + int dy = vector.y() - center.y(); + int dz = vector.z() - center.z(); Vector3 pos1 = transform.apply(mutable.setComponents(dx - 0.5, dy - 0.5, dz - 0.5)); - int x1 = (int) (pos1.getX() * scale + centerImageX); - int z1 = (int) (pos1.getZ() * scale + centerImageZ); + int x1 = (int) (pos1.x() * scale + centerImageX); + int z1 = (int) (pos1.z() * scale + centerImageZ); Vector3 pos2 = transform.apply(mutable.setComponents(dx + 0.5, dy + 0.5, dz + 0.5)); - int x2 = (int) (pos2.getX() * scale + centerImageX); - int z2 = (int) (pos2.getZ() * scale + centerImageZ); + int x2 = (int) (pos2.x() * scale + centerImageX); + int z2 = (int) (pos2.z() * scale + centerImageZ); if (x2 < x1) { int tmp = x1; x1 = x2; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/LayerBrushMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/LayerBrushMask.java index 825039ed0..7f30ab64a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/LayerBrushMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/LayerBrushMask.java @@ -40,20 +40,20 @@ public class LayerBrushMask extends AbstractExtentMask { BlockState previous2 = layers[depth - 2]; for (BlockVector3 dir : BreadthFirstSearch.DEFAULT_DIRECTIONS) { mutable.setComponents( - pos.getBlockX() + dir.getBlockX(), - pos.getBlockY() + dir.getBlockY(), - pos.getBlockZ() + dir.getBlockZ() + pos.x() + dir.x(), + pos.y() + dir.y(), + pos.z() + dir.z() ); if (visitor.isVisited(mutable) && editSession.getBlock( - mutable.getBlockX(), - mutable.getBlockY(), - mutable.getBlockZ() + mutable.x(), + mutable.y(), + mutable.z() ) == previous) { - mutable.setComponents(pos.getBlockX() + dir.getBlockX() * 2, pos.getBlockY() + dir.getBlockY() * 2, - pos.getBlockZ() + dir.getBlockZ() * 2 + mutable.setComponents(pos.x() + dir.x() * 2, pos.y() + dir.y() * 2, + pos.z() + dir.z() * 2 ); if (visitor.isVisited(mutable) - && editSession.getBlock(mutable.getBlockX(), mutable.getBlockY(), mutable.getBlockZ()) == previous2) { + && editSession.getBlock(mutable.x(), mutable.y(), mutable.z()) == previous2) { found = true; break; } else { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/PlaneMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/PlaneMask.java index 6b8b1e4a1..5de393940 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/PlaneMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/PlaneMask.java @@ -15,9 +15,9 @@ public class PlaneMask extends AbstractMask implements ResettableMask { public boolean test(BlockVector3 vector) { switch (mode) { case -1: - originX = vector.getBlockX(); - originY = vector.getBlockY(); - originZ = vector.getBlockZ(); + originX = vector.x(); + originY = vector.y(); + originZ = vector.z(); mode = 0; return true; case 0: @@ -25,13 +25,13 @@ public class PlaneMask extends AbstractMask implements ResettableMask { case 2: case 4: int original = mode; - if (originX != vector.getBlockX()) { + if (originX != vector.x()) { mode &= 1; } - if (originY != vector.getBlockY()) { + if (originY != vector.y()) { mode &= 2; } - if (originZ != vector.getBlockZ()) { + if (originZ != vector.z()) { mode &= 4; } if (Integer.bitCount(mode) >= 3) { @@ -39,13 +39,13 @@ public class PlaneMask extends AbstractMask implements ResettableMask { return false; } default: - if (originX != vector.getBlockX() && (mode & 1) == 0) { + if (originX != vector.x() && (mode & 1) == 0) { return false; } - if (originZ != vector.getBlockZ() && (mode & 4) == 0) { + if (originZ != vector.z() && (mode & 4) == 0) { return false; } - return originY == vector.getBlockY() || (mode & 2) != 0; + return originY == vector.y() || (mode & 2) != 0; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/RadiusMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/RadiusMask.java index b99e56ddc..c8893ae79 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/RadiusMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/RadiusMask.java @@ -30,17 +30,17 @@ public class RadiusMask extends AbstractMask implements ResettableMask { if (pos == null) { pos = to.toImmutable(); } - int dx = pos.getBlockX() - to.getBlockX(); + int dx = pos.x() - to.x(); int d = dx * dx; if (d > maxSqr) { return false; } - int dz = pos.getBlockZ() - to.getBlockZ(); + int dz = pos.z() - to.z(); d += dz * dz; if (d > maxSqr) { return false; } - int dy = pos.getBlockY() - to.getBlockY(); + int dy = pos.y() - to.y(); d += dy * dy; return d >= minSqr && d <= maxSqr; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SimplexMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SimplexMask.java index d337cd61a..a56238918 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SimplexMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SimplexMask.java @@ -19,7 +19,7 @@ public class SimplexMask extends AbstractMask { @Override public boolean test(BlockVector3 vector) { - double value = SimplexNoise.noise(vector.getBlockX() * scale, vector.getBlockY() * scale, vector.getBlockZ() * scale); + double value = SimplexNoise.noise(vector.x() * scale, vector.y() * scale, vector.z() * scale); return value >= min && value <= max; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java index 32d853bda..400f32163 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java @@ -30,7 +30,7 @@ public class SingleBlockStateMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); return ordinal == test || isAir && test == 0; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java index 250969616..d80399be4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java @@ -40,7 +40,7 @@ public class SplatterBrushMask extends AbstractExtentMask { double dist = vector.distanceSq(position); synchronized (placed) { if (dist < size2 && !placed.contains(vector) && ThreadLocalRandom.current().nextInt(5) < 2 && surface.test(vector)) { - placed.add(vector); + placed.add(vector.toImmutable()); return true; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/StencilBrushMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/StencilBrushMask.java index 3100f6a9e..25ee249d8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/StencilBrushMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/StencilBrushMask.java @@ -64,13 +64,13 @@ public class StencilBrushMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { if (solid.test(vector)) { - int dx = vector.getBlockX() - center.getBlockX(); - int dy = vector.getBlockY() - center.getBlockY(); - int dz = vector.getBlockZ() - center.getBlockZ(); + int dx = vector.x() - center.x(); + int dy = vector.y() - center.y(); + int dz = vector.z() - center.z(); Vector3 srcPos = transform.apply(mutable.setComponents(dx, dy, dz)); - dx = MathMan.roundInt(srcPos.getX()); - dz = MathMan.roundInt(srcPos.getZ()); + dx = MathMan.roundInt(srcPos.x()); + dz = MathMan.roundInt(srcPos.z()); int distance = dx * dx + dz * dz; if (distance > size2 || Math.abs(dx) > 256 || Math.abs(dz) > 256) { @@ -83,7 +83,7 @@ public class StencilBrushMask extends AbstractExtentMask { return true; } if (val >= 255 || ThreadLocalRandom.current().nextInt(maxY) < val) { - editSession.setBlock(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), pattern); + editSession.setBlock(vector.x(), vector.y(), vector.z(), pattern); } return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SurfaceAngleMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SurfaceAngleMask.java index ce42a2d7e..15b347dbc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SurfaceAngleMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SurfaceAngleMask.java @@ -24,7 +24,7 @@ public class SurfaceAngleMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { if (!vector.getBlock(getExtent()).isAir() && nextToAir(vector)) { - double angle = 1 - getAverageAirDirection(vector.toVector3(), size).getY(); + double angle = 1 - getAverageAirDirection(vector.toVector3(), size).y(); return (angle >= (min / 90.0) && angle <= (max / 90.0)); } return false; @@ -33,7 +33,7 @@ public class SurfaceAngleMask extends AbstractExtentMask { @Override public boolean test(Extent extent, BlockVector3 vector) { if (!vector.getBlock(getExtent()).isAir() && nextToAir(vector)) { - double angle = 1 - getAverageAirDirection(vector.toVector3(), size).getY(); + double angle = 1 - getAverageAirDirection(vector.toVector3(), size).y(); return (angle >= (min / 90.0) && angle <= (max / 90.0)); } return false; @@ -44,7 +44,7 @@ public class SurfaceAngleMask extends AbstractExtentMask { for (int i = -size; i <= size; i++) { for (int j = -size; j <= size; j++) { for (int k = -size; k <= size; k++) { - Vector3 block = Vector3.at(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ()).add( + Vector3 block = Vector3.at(currentLocation.x(), currentLocation.y(), currentLocation.z()).add( 0.5, 0.5, 0.5 @@ -65,13 +65,13 @@ public class SurfaceAngleMask extends AbstractExtentMask { double y = 0.0; double z = 0.0; for (Vector3 vector3 : airDirections) { - x += vector3.getX(); - y += vector3.getY(); - z += vector3.getZ(); + x += vector3.x(); + y += vector3.y(); + z += vector3.z(); } Vector3 averageAirDirection = Vector3.at(x / airDirections.size(), y / airDirections.size(), z / airDirections.size()); - return (Double.isNaN(averageAirDirection.getY()) ? Vector3.ZERO : averageAirDirection.normalize()); + return (Double.isNaN(averageAirDirection.y()) ? Vector3.ZERO : averageAirDirection.normalize()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMakeMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMakeMask.java index 4246f8a82..9d7b7a729 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMakeMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMakeMask.java @@ -14,8 +14,8 @@ public class WallMakeMask implements Mask { @Override public boolean test(BlockVector3 position) { - int x = position.getBlockX(); - int z = position.getBlockZ(); + int x = position.x(); + int z = position.z(); return !region.contains(x, z + 1) || !region.contains(x, z - 1) || !region.contains(x + 1, z) || !region.contains( x - 1, z diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMask.java index 40a323e51..eee5ab286 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/WallMask.java @@ -23,9 +23,9 @@ public class WallMask extends AbstractMask { public boolean test(BlockVector3 bv) { vector.setComponents(bv); int count = 0; - double x = vector.getX(); - double y = vector.getY(); - double z = vector.getZ(); + double x = vector.x(); + double y = vector.y(); + double z = vector.z(); vector.mutX(x + 1); if (mask.test(vector) && ++count == min && max >= 8) { vector.mutX(x); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/XAxisMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/XAxisMask.java index 7531d1465..82c0eca02 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/XAxisMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/XAxisMask.java @@ -16,9 +16,9 @@ public class XAxisMask extends AbstractMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { if (layer == -1) { - layer = vector.getBlockX(); + layer = vector.x(); } - return vector.getBlockX() == layer; + return vector.x() == layer; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/YAxisMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/YAxisMask.java index ee852e70e..15ee08192 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/YAxisMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/YAxisMask.java @@ -14,9 +14,9 @@ public class YAxisMask extends AbstractMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { if (layer == -1) { - layer = vector.getBlockY(); + layer = vector.y(); } - return vector.getBlockY() == layer; + return vector.y() == layer; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ZAxisMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ZAxisMask.java index 269fc5dd8..648b712d2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ZAxisMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ZAxisMask.java @@ -14,9 +14,9 @@ public class ZAxisMask extends AbstractMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { if (layer == -1) { - layer = vector.getBlockZ(); + layer = vector.z(); } - return vector.getBlockZ() == layer; + return vector.z() == layer; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java index a13061951..9f2becf76 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java @@ -42,9 +42,9 @@ public class AngleColorPattern extends AnglePattern { public > int getSlope(T block, BlockVector3 vector, Extent extent) { int slope = super.getSlope(block, vector, extent); if (slope != -1) { - int x = vector.getBlockX(); - int y = vector.getBlockY(); - int z = vector.getBlockZ(); + int x = vector.x(); + int y = vector.y(); + int z = vector.z(); int height = extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); if (height > minY) { BlockState below = extent.getBlock(x, height - 1, z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AnglePattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AnglePattern.java index 224d64434..caebfd6ff 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AnglePattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AnglePattern.java @@ -31,9 +31,9 @@ public abstract class AnglePattern extends AbstractPattern { } public > int getSlope(T block, BlockVector3 vector, Extent extent) { - int x = vector.getBlockX(); - int y = vector.getBlockY(); - int z = vector.getBlockZ(); + int x = vector.x(); + int y = vector.y(); + int z = vector.z(); if (!block.getBlockType().getMaterial().isMovementBlocker()) { return -1; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/BufferedPattern2D.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/BufferedPattern2D.java index 99414ca25..7748c8633 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/BufferedPattern2D.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/BufferedPattern2D.java @@ -33,7 +33,7 @@ public class BufferedPattern2D extends BufferedPattern { @Override public boolean set(BlockVector3 pos) { - return set.add(pos.getBlockX(), 0, pos.getBlockY()); + return set.add(pos.x(), 0, pos.z()); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ExpressionPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ExpressionPattern.java index a9c1ec962..9276acb40 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ExpressionPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ExpressionPattern.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.function.pattern; import com.sk89q.worldedit.function.pattern.AbstractPattern; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.expression.EvaluationException; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; @@ -49,7 +50,7 @@ public class ExpressionPattern extends AbstractPattern { if (expression.getEnvironment() instanceof WorldEditExpressionEnvironment) { ((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector.toVector3()); } - double combined = expression.evaluate(vector.getX(), vector.getY(), vector.getZ()); + double combined = expression.evaluate(vector.x(), vector.y(), vector.z()); return BlockState.getFromOrdinal((int) combined).toBaseBlock(); } catch (EvaluationException e) { e.printStackTrace(); @@ -57,4 +58,9 @@ public class ExpressionPattern extends AbstractPattern { } } + @Override + public Pattern fork() { + return new ExpressionPattern(this.expression.clone()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear2DBlockPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear2DBlockPattern.java index 7c923c4d4..d30206534 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear2DBlockPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear2DBlockPattern.java @@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; +import java.util.Arrays; + import static java.lang.Math.floorDiv; +/** + * @deprecated replaced by {@link com.sk89q.worldedit.function.pattern.RandomPattern} + * combined with {@link com.fastasyncworldedit.core.math.random.Linear2DRandom}. + */ +@Deprecated(forRemoval = true, since = "2.9.2") public class Linear2DBlockPattern extends AbstractPattern { private final Pattern[] patternsArray; @@ -30,7 +37,7 @@ public class Linear2DBlockPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - int index = (position.getBlockX() / this.xScale + position.getBlockZ() / this.zScale) % patternsArray.length; + int index = (position.x() / this.xScale + position.z() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } @@ -39,12 +46,18 @@ public class Linear2DBlockPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - int index = (floorDiv(get.getBlockX(), this.xScale) - + floorDiv(get.getBlockZ(), this.zScale)) % patternsArray.length; + int index = (floorDiv(get.x(), this.xScale) + + floorDiv(get.z(), this.zScale)) % patternsArray.length; if (index < 0) { index += patternsArray.length; } return patternsArray[index].apply(extent, get, set); } + @Override + public Pattern fork() { + final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new); + return new Linear2DBlockPattern(forked, this.xScale, this.zScale); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear3DBlockPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear3DBlockPattern.java index 04028244d..de6e3257b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear3DBlockPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/Linear3DBlockPattern.java @@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; +import java.util.Arrays; + import static java.lang.Math.floorDiv; +/** + * @deprecated replaced by {@link com.sk89q.worldedit.function.pattern.RandomPattern} + * combined with {@link com.fastasyncworldedit.core.math.random.Linear3DRandom}. + */ +@Deprecated(forRemoval = true, since = "2.9.2") public class Linear3DBlockPattern extends AbstractPattern { private final Pattern[] patternsArray; @@ -33,8 +40,8 @@ public class Linear3DBlockPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - int index = (position.getBlockX() / this.xScale - + position.getBlockY() / this.yScale + position.getBlockZ() / this.zScale) % patternsArray.length; + int index = (position.x() / this.xScale + + position.y() / this.yScale + position.z() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } @@ -43,12 +50,18 @@ public class Linear3DBlockPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - int index = (floorDiv(get.getBlockX(), this.xScale) - + floorDiv(get.getBlockY(), this.yScale) + floorDiv(get.getBlockZ(), this.zScale)) % patternsArray.length; + int index = (floorDiv(get.x(), this.xScale) + + floorDiv(get.y(), this.yScale) + floorDiv(get.z(), this.zScale)) % patternsArray.length; if (index < 0) { index += patternsArray.length; } return patternsArray[index].apply(extent, get, set); } + @Override + public Pattern fork() { + final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new); + return new Linear3DBlockPattern(forked, this.xScale, this.yScale, this.zScale); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/LinearBlockPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/LinearBlockPattern.java index 086cf3a31..1490bf37d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/LinearBlockPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/LinearBlockPattern.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.function.pattern; +import com.fastasyncworldedit.core.queue.Filter; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; @@ -7,6 +8,8 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; +import java.util.Arrays; + public class LinearBlockPattern extends AbstractPattern implements ResettablePattern { private final Pattern[] patternsArray; @@ -15,7 +18,7 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat /** * Create a new {@link Pattern} instance * - * @param patterns array of patterns to linearly choose from based on x/z coordinates + * @param patterns array of patterns to linearly choose from */ public LinearBlockPattern(Pattern[] patterns) { this.patternsArray = patterns; @@ -23,18 +26,14 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat @Override public BaseBlock applyBlock(BlockVector3 position) { - if (index == patternsArray.length) { - index = 0; - } - return patternsArray[index++].applyBlock(position); + index = (index + 1) % patternsArray.length; + return patternsArray[index].applyBlock(position); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - if (index == patternsArray.length) { - index = 0; - } - return patternsArray[index++].apply(extent, get, set); + index = (index + 1) % patternsArray.length; + return patternsArray[index].apply(extent, get, set); } @Override @@ -42,4 +41,10 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat index = 0; } + @Override + public Pattern fork() { + final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new); + return new LinearBlockPattern(forked); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/MaskedPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/MaskedPattern.java index 5d840d771..a5210feba 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/MaskedPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/MaskedPattern.java @@ -43,4 +43,9 @@ public class MaskedPattern extends AbstractPattern { return secondary.apply(extent, get, set); } + @Override + public Pattern fork() { + return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoXPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoXPattern.java index d9fefb1bc..2d4da9528 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoXPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoXPattern.java @@ -24,16 +24,21 @@ public class NoXPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 pos) { - mutable.mutY(pos.getY()); - mutable.mutZ(pos.getZ()); + mutable.mutY(pos.y()); + mutable.mutZ(pos.z()); return pattern.applyBlock(mutable); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutY(get.getY()); - mutable.mutZ(get.getZ()); + mutable.mutY(get.y()); + mutable.mutZ(get.z()); return pattern.apply(extent, mutable, set); } + @Override + public Pattern fork() { + return new NoXPattern(this.pattern.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoYPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoYPattern.java index 05d26f496..12ef8174d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoYPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoYPattern.java @@ -24,16 +24,21 @@ public class NoYPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 pos) { - mutable.mutX(pos.getX()); - mutable.mutZ(pos.getZ()); + mutable.mutX(pos.x()); + mutable.mutZ(pos.z()); return pattern.applyBlock(mutable); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutX(get.getX()); - mutable.mutZ(get.getZ()); + mutable.mutX(get.x()); + mutable.mutZ(get.z()); return pattern.apply(extent, mutable, set); } + @Override + public Pattern fork() { + return new NoYPattern(this.pattern.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoZPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoZPattern.java index faebb59aa..f4d2a47ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoZPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/NoZPattern.java @@ -24,16 +24,21 @@ public class NoZPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 pos) { - mutable.mutX(pos.getX()); - mutable.mutY(pos.getY()); + mutable.mutX(pos.x()); + mutable.mutY(pos.y()); return pattern.applyBlock(mutable); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutX(get.getX()); - mutable.mutY(get.getY()); + mutable.mutX(get.x()); + mutable.mutY(get.y()); return pattern.apply(extent, mutable, set); } + @Override + public Pattern fork() { + return new NoZPattern(this.pattern.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/OffsetPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/OffsetPattern.java index 894f9d06a..5866766ef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/OffsetPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/OffsetPattern.java @@ -40,10 +40,10 @@ public class OffsetPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - mutable.mutX(position.getX() + dx); - mutable.mutY(position.getY() + dy); - mutable.mutZ(position.getZ() + dz); - if (mutable.getY() < minY || mutable.getY() > maxY) { + mutable.mutX(position.x() + dx); + mutable.mutY(position.y() + dy); + mutable.mutZ(position.z() + dz); + if (mutable.y() < minY || mutable.y() > maxY) { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } return pattern.applyBlock(mutable); @@ -51,13 +51,25 @@ public class OffsetPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutX(get.getX() + dx); - mutable.mutY(get.getY() + dy); - mutable.mutZ(get.getZ() + dz); - if (mutable.getY() < extent.getMinY() || mutable.getY() > extent.getMaxY()) { + mutable.mutX(get.x() + dx); + mutable.mutY(get.y() + dy); + mutable.mutZ(get.z() + dz); + if (mutable.y() < extent.getMinY() || mutable.y() > extent.getMaxY()) { return false; } return pattern.apply(extent, get, mutable); } + @Override + public BlockVector3 size() { + // Not exactly the "size" but offset should be taken into consideration in most + // places where the "size" matters + return BlockVector3.at(dx, dy, dz); + } + + @Override + public Pattern fork() { + return new OffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomFullClipboardPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomFullClipboardPattern.java index 52348780b..957cf2617 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomFullClipboardPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomFullClipboardPattern.java @@ -1,7 +1,9 @@ package com.fastasyncworldedit.core.function.pattern; +import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -9,6 +11,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.world.block.BaseBlock; @@ -23,6 +27,7 @@ public class RandomFullClipboardPattern extends AbstractPattern { private final boolean randomRotate; private final boolean randomFlip; private final Vector3 flipVector = Vector3.at(1, 0, 0).multiply(-2).add(1, 1, 1); + private final BlockVector3 size; /** * Create a new {@link Pattern} instance @@ -34,6 +39,12 @@ public class RandomFullClipboardPattern extends AbstractPattern { public RandomFullClipboardPattern(List clipboards, boolean randomRotate, boolean randomFlip) { checkNotNull(clipboards); this.clipboards = clipboards; + MutableBlockVector3 mut = new MutableBlockVector3(); + clipboards.stream().flatMap(c -> c.getClipboards().stream()).map(c -> { + Region region = c.getRegion(); + return region.getMaximumPoint().subtract(c.getOrigin().getMinimum(region.getMinimumPoint())); + }).forEach(mut::getMaximum); + this.size = mut.toImmutable(); this.randomRotate = randomRotate; this.randomFlip = randomFlip; } @@ -66,4 +77,9 @@ public class RandomFullClipboardPattern extends AbstractPattern { throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!"); } + @Override + public BlockVector3 size() { + return size; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomOffsetPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomOffsetPattern.java index 3eb5c3b77..5dc012f66 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomOffsetPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RandomOffsetPattern.java @@ -52,10 +52,10 @@ public class RandomOffsetPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - mutable.mutX((position.getX() + r.nextInt(dx2) - dx)); - mutable.mutY((position.getY() + r.nextInt(dy2) - dy)); - mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); - if (mutable.getY() < minY || mutable.getY() > maxY) { + mutable.mutX((position.x() + r.nextInt(dx2) - dx)); + mutable.mutY((position.y() + r.nextInt(dy2) - dy)); + mutable.mutZ((position.z() + r.nextInt(dz2) - dz)); + if (mutable.y() < minY || mutable.y() > maxY) { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } return pattern.applyBlock(mutable); @@ -63,13 +63,23 @@ public class RandomOffsetPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutX((set.getX() + r.nextInt(dx2) - dx)); - mutable.mutY((set.getY() + r.nextInt(dy2) - dy)); - mutable.mutZ((set.getZ() + r.nextInt(dz2) - dz)); - if (mutable.getY() < extent.getMinY() || mutable.getY() > extent.getMaxY()) { + mutable.mutX((set.x() + r.nextInt(dx2) - dx)); + mutable.mutY((set.y() + r.nextInt(dy2) - dy)); + mutable.mutZ((set.z() + r.nextInt(dz2) - dz)); + if (mutable.y() < extent.getMinY() || mutable.y() > extent.getMaxY()) { return false; } return pattern.apply(extent, get, mutable); } + @Override + public BlockVector3 size() { + return BlockVector3.at(dx2, dy2, dz2); + } + + @Override + public Pattern fork() { + return new RandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RelativePattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RelativePattern.java index cda875f04..22e3a8d0b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RelativePattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/RelativePattern.java @@ -35,10 +35,10 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter if (origin == null) { origin = pos; } - mutable.mutX(pos.getX() - origin.getX()); - mutable.mutY(pos.getY() - origin.getY()); - mutable.mutZ(pos.getZ() - origin.getZ()); - if (mutable.getY() < minY || mutable.getY() > maxY) { + mutable.mutX(pos.x() - origin.x()); + mutable.mutY(pos.y() - origin.y()); + mutable.mutZ(pos.z() - origin.z()); + if (mutable.y() < minY || mutable.y() > maxY) { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } return pattern.applyBlock(mutable); @@ -49,10 +49,10 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter if (origin == null) { origin = set; } - mutable.mutX(set.getX() - origin.getX()); - mutable.mutY(set.getY() - origin.getY()); - mutable.mutZ(set.getZ() - origin.getZ()); - if (mutable.getY() < extent.getMinY() || mutable.getY() > extent.getMaxY()) { + mutable.mutX(set.x() - origin.x()); + mutable.mutY(set.y() - origin.y()); + mutable.mutZ(set.z() - origin.z()); + if (mutable.y() < extent.getMinY() || mutable.y() > extent.getMaxY()) { return false; } return pattern.apply(extent, get, mutable); @@ -63,4 +63,11 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter origin = null; } + @Override + public Pattern fork() { + RelativePattern forked = new RelativePattern(this.pattern.fork(), this.minY, this.maxY); + forked.origin = this.origin; // maintain origin for forks + return forked; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SolidRandomOffsetPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SolidRandomOffsetPattern.java index 12b64a497..698c0f199 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SolidRandomOffsetPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SolidRandomOffsetPattern.java @@ -63,13 +63,13 @@ public class SolidRandomOffsetPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - mutable.mutX(position.getX() + r.nextInt(dx2) - dx); - mutable.mutY(position.getY() + r.nextInt(dy2) - dy); - mutable.mutZ(position.getZ() + r.nextInt(dz2) - dz); - if (mutable.getY() < minY || mutable.getY() > maxY) { + mutable.mutX(position.x() + r.nextInt(dx2) - dx); + mutable.mutY(position.y() + r.nextInt(dy2) - dy); + mutable.mutZ(position.z() + r.nextInt(dz2) - dz); + if (mutable.y() < minY || mutable.y() > maxY) { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - if (mutable.getY() < minY || mutable.getY() > maxY) { + if (mutable.y() < minY || mutable.y() > maxY) { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } BaseBlock block = pattern.applyBlock(mutable); @@ -81,10 +81,10 @@ public class SolidRandomOffsetPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - mutable.mutX(set.getX() + r.nextInt(dx2) - dx); - mutable.mutY(set.getY() + r.nextInt(dy2) - dy); - mutable.mutZ(set.getZ() + r.nextInt(dz2) - dz); - if (mutable.getY() < extent.getMinY() || mutable.getY() > extent.getMaxY()) { + mutable.mutX(set.x() + r.nextInt(dx2) - dx); + mutable.mutY(set.y() + r.nextInt(dy2) - dy); + mutable.mutZ(set.z() + r.nextInt(dz2) - dz); + if (mutable.y() < extent.getMinY() || mutable.y() > extent.getMaxY()) { return false; } BaseBlock block = pattern.applyBlock(mutable); @@ -94,4 +94,9 @@ public class SolidRandomOffsetPattern extends AbstractPattern { return pattern.apply(extent, get, set); } + @Override + public Pattern fork() { + return new SolidRandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SurfaceRandomOffsetPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SurfaceRandomOffsetPattern.java index 73327f94a..a7a1a3e2e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SurfaceRandomOffsetPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SurfaceRandomOffsetPattern.java @@ -62,9 +62,9 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { next = buffer[i]; BlockVector3 dir = BreadthFirstSearch.DIAGONAL_DIRECTIONS[i]; next.setComponents( - cur.getBlockX() + dir.getBlockX(), - cur.getBlockY() + dir.getBlockY(), - cur.getBlockZ() + dir.getBlockZ() + cur.x() + dir.x(), + cur.y() + dir.y(), + cur.z() + dir.z() ); if (allowed(next)) { allowed[index++] = next; @@ -74,7 +74,7 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { return cur; } next = allowed[ThreadLocalRandom.current().nextInt(index)]; - cur.setComponents(next.getBlockX(), next.getBlockY(), next.getBlockZ()); + cur.setComponents(next.x(), next.y(), next.z()); } return cur; } @@ -85,9 +85,9 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { if (!block.getBlockType().getMaterial().isMovementBlocker()) { return false; } - int x = v.getBlockX(); - int y = v.getBlockY(); - int z = v.getBlockZ(); + int x = v.x(); + int y = v.y(); + int z = v.z(); v.mutY(y + 1); if (y < maxY && canPassthrough(v)) { v.mutY(y); @@ -129,4 +129,14 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { return !block.getBlockType().getMaterial().isMovementBlocker(); } + @Override + public BlockVector3 size() { + return BlockVector3.at(moves, moves, moves); + } + + @Override + public Pattern fork() { + return new SurfaceRandomOffsetPattern(this.pattern.fork(), this.moves, this.minY, this.maxY); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/TypeSwapPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/TypeSwapPattern.java index efc122b5d..d222833a7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/TypeSwapPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/TypeSwapPattern.java @@ -79,7 +79,7 @@ public class TypeSwapPattern extends AbstractExtentPattern { } private BlockState getNewBlock(BlockState existing) { - String oldId = existing.getBlockType().getId(); + String oldId = existing.getBlockType().id(); String newId = oldId; if (inputPattern != null) { newId = inputPattern.matcher(oldId).replaceAll(outputString); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/AboveVisitor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/AboveVisitor.java index d2503447b..67a48e2f7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/AboveVisitor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/AboveVisitor.java @@ -40,7 +40,7 @@ public class AboveVisitor extends RecursiveVisitor { @Override public boolean isVisitable(BlockVector3 from, BlockVector3 to) { - return (from.getBlockY() >= baseY) && super.isVisitable(from, to); + return (from.y() >= baseY) && super.isVisitable(from, to); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DFSVisitor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DFSVisitor.java index 58b6f0e41..6a84af071 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DFSVisitor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DFSVisitor.java @@ -64,13 +64,13 @@ public abstract class DFSVisitor implements Operation { IntTriple[] array = new IntTriple[directions.size()]; for (int i = 0; i < array.length; i++) { BlockVector3 dir = directions.get(i); - array[i] = new IntTriple(dir.getBlockX(), dir.getBlockY(), dir.getBlockZ()); + array[i] = new IntTriple(dir.x(), dir.y(), dir.z()); } return array; } public void visit(final BlockVector3 pos) { - Node node = new Node(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); + Node node = new Node(pos.x(), pos.y(), pos.z()); if (!this.hashQueue.contains(node)) { isVisitable(pos, pos); // Ignore this, just to initialize mask on this point queue.addFirst(new NodePair(null, node, 0)); @@ -102,7 +102,7 @@ public abstract class DFSVisitor implements Operation { mutable2.mutY(from.getY() + direction.y()); mutable2.mutZ(from.getZ() + direction.z()); if (isVisitable(mutable, mutable2)) { - Node adjacent = new Node(mutable2.getBlockX(), mutable2.getBlockY(), mutable2.getBlockZ()); + Node adjacent = new Node(mutable2.x(), mutable2.y(), mutable2.z()); if (!adjacent.equals(current.from)) { AtomicInteger adjacentCount = visited.get(adjacent); if (adjacentCount == null) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DirectionalVisitor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DirectionalVisitor.java index b7b14059b..f77b0b66b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DirectionalVisitor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/visitor/DirectionalVisitor.java @@ -52,22 +52,22 @@ public class DirectionalVisitor extends RecursiveVisitor { @Override public boolean isVisitable(final BlockVector3 from, final BlockVector3 to) { - int dx = to.getBlockX() - from.getBlockX(); - int dz = to.getBlockZ() - from.getBlockZ(); - int dy = to.getBlockY() - from.getBlockY(); + int dx = to.x() - from.x(); + int dz = to.z() - from.z(); + int dy = to.y() - from.y(); if (dx != 0) { - if (dirVec.getBlockX() != 0 && dirVec.getBlockX() != dx) { + if (dirVec.x() != 0 && dirVec.x() != dx) { return false; } } if (dy != 0) { - if (dirVec.getBlockY() != 0 && dirVec.getBlockY() != dy) { + if (dirVec.y() != 0 && dirVec.y() != dy) { return false; } } if (dz != 0) { - if (dirVec.getBlockZ() != 0 && dirVec.getBlockZ() != dz) { + if (dirVec.z() != 0 && dirVec.z() != dz) { return false; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/DiskStorageHistory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/DiskStorageHistory.java index 7d0bfe76e..eb2e3da59 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/DiskStorageHistory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/DiskStorageHistory.java @@ -15,8 +15,10 @@ import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.operation.ChangeSetExecutor; +import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; +import org.apache.logging.log4j.Logger; import java.io.File; import java.io.FileInputStream; @@ -35,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public class DiskStorageHistory extends FaweStreamChangeSet { + private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Map> NEXT_INDEX = new ConcurrentHashMap<>(); private UUID uuid; @@ -141,9 +144,9 @@ public class DiskStorageHistory extends FaweStreamChangeSet { e.printStackTrace(); return; } - EditSession session = toEditSession(actor, regions); - session.setBlocks(this, ChangeSetExecutor.Type.UNDO); - deleteFiles(); + try (EditSession session = toEditSession(actor, regions)) { + session.setBlocks(this, ChangeSetExecutor.Type.UNDO); + } } public void undo(Actor actor) { @@ -371,9 +374,14 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!bdFile.exists()) { return null; } - FaweInputStream is = MainUtil.getCompressedIS(new FileInputStream(bdFile)); - readHeader(is); - return is; + try { + FaweInputStream is = MainUtil.getCompressedIS(new FileInputStream(bdFile)); + readHeader(is); + return is; + } catch (IOException e) { + LOGGER.error("Could not load block history file {}", bdFile); + throw e; + } } @Override @@ -381,7 +389,12 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!bioFile.exists()) { return null; } - return MainUtil.getCompressedIS(new FileInputStream(bioFile)); + try { + return MainUtil.getCompressedIS(new FileInputStream(bioFile)); + } catch (IOException e) { + LOGGER.error("Could not load biome history file {}", bdFile); + throw e; + } } @Override @@ -389,7 +402,12 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!enttFile.exists()) { return null; } - return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(enttFile))); + try { + return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(enttFile))); + } catch (IOException e) { + LOGGER.error("Could not load entity create history file {}", bdFile); + throw e; + } } @Override @@ -397,7 +415,12 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!entfFile.exists()) { return null; } - return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(entfFile))); + try { + return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(entfFile))); + } catch (IOException e) { + LOGGER.error("Could not load entity remove history file {}", bdFile); + throw e; + } } @Override @@ -405,7 +428,12 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!nbttFile.exists()) { return null; } - return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(nbttFile))); + try { + return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(nbttFile))); + } catch (IOException e) { + LOGGER.error("Could not load tile create history file {}", bdFile); + throw e; + } } @Override @@ -413,7 +441,12 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (!nbtfFile.exists()) { return null; } - return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(nbtfFile))); + try { + return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(nbtfFile))); + } catch (IOException e) { + LOGGER.error("Could not load tile remove history file {}", bdFile); + throw e; + } } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/RollbackOptimizedHistory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/RollbackOptimizedHistory.java index 6e7e4068b..e11fda2b1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/RollbackOptimizedHistory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/RollbackOptimizedHistory.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BiomeType; import org.apache.logging.log4j.Logger; import java.io.IOException; @@ -83,12 +84,12 @@ public class RollbackOptimizedHistory extends DiskStorageHistory { } public void setDimensions(BlockVector3 pos1, BlockVector3 pos2) { - this.minX = pos1.getBlockX(); - this.minY = pos1.getBlockY(); - this.minZ = pos1.getBlockZ(); - this.maxX = pos2.getBlockX(); - this.maxY = pos2.getBlockY(); - this.maxZ = pos2.getBlockZ(); + this.minX = pos1.x(); + this.minY = pos1.y(); + this.minZ = pos1.z(); + this.maxX = pos2.x(); + this.maxY = pos2.y(); + this.maxZ = pos2.z(); } public void setTime(long time) { @@ -125,6 +126,26 @@ public class RollbackOptimizedHistory extends DiskStorageHistory { } } + @Override + public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { + super.addBiomeChange(x, y, z, from, to); + if (x < minX) { + minX = x; + } else if (x > maxX) { + maxX = x; + } + if (y < minY) { + minY = y; + } else if (y > maxY) { + maxY = y; + } + if (z < minZ) { + minZ = z; + } else if (z > maxZ) { + maxZ = z; + } + } + @Override public void writeHeader(OutputStream os, int x, int y, int z) throws IOException { minX = x; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java new file mode 100644 index 000000000..84424d948 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java @@ -0,0 +1,65 @@ +package com.fastasyncworldedit.core.history.change; + +import com.sk89q.worldedit.history.change.Change; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @since 2.11.2 + */ +@ApiStatus.Internal +public interface ChangePopulator { + + static ChangePopulator empty() { + class Empty implements ChangePopulator { + private static final Empty EMPTY = new Empty(); + + @Override + public @NotNull C create() { + throw new UnsupportedOperationException("empty"); + } + + @Override + public @Nullable C populate(@NotNull final C change) { + return null; + } + + @Override + public @Nullable C updateOrCreate(@Nullable final Change change) { + return null; + } + + @Override + public boolean accepts(final Change change) { + return false; + } + } + return Empty.EMPTY; + } + + @SuppressWarnings("unchecked") + default @NotNull C update(@Nullable Change before) { + if (accepts(before)) { + return (C) before; + } + return create(); + } + + @NotNull + C create(); + + @Nullable + default C updateOrCreate(@Nullable Change change) { + C u = update(change); + return populate(u); + } + + @Nullable + C populate(@NotNull C change); + + @Contract("null->false") + boolean accepts(Change change); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableEntityChange.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableEntityChange.java index 7fa4ddc6d..b56ebc3eb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableEntityChange.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableEntityChange.java @@ -3,7 +3,6 @@ package com.fastasyncworldedit.core.history.change; import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; @@ -52,7 +51,7 @@ public class MutableEntityChange implements Change { @SuppressWarnings({"unchecked"}) public void delete(UndoContext context) { - Map map = tag.getValue(); + Map> map = tag.getValue(); UUID uuid = tag.getUUID(); if (uuid == null) { LOGGER.info("Skipping entity without uuid."); @@ -66,7 +65,7 @@ public class MutableEntityChange implements Change { } public void create(UndoContext context) { - Map map = tag.getValue(); + Map> map = tag.getValue(); Tag posTag = map.get("Pos"); if (posTag == null) { LOGGER.warn("Missing pos tag: {}", tag); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index b3493c896..33931aac6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -4,11 +4,12 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.HistoryExtent; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.util.MainUtil; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.util.concurrent.Futures; import com.sk89q.jnbt.CompoundTag; @@ -32,8 +33,12 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.jetbrains.annotations.ApiStatus; +import javax.annotation.Nonnull; import java.io.IOException; +import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Objects; @@ -122,37 +127,38 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { int bx = chunk.getX() << 4; int bz = chunk.getZ() << 4; - Map tilesFrom = get.getTiles(); - Map tilesTo = set.getTiles(); + Map tilesFrom = get.tiles(); + Map tilesTo = set.tiles(); if (!tilesFrom.isEmpty()) { - for (Map.Entry entry : tilesFrom.entrySet()) { + for (Map.Entry entry : tilesFrom.entrySet()) { BlockVector3 pos = entry.getKey(); - BlockState fromBlock = get.getBlock(pos.getX() & 15, pos.getY(), pos.getZ() & 15); - BlockState toBlock = set.getBlock(pos.getX() & 15, pos.getY(), pos.getZ() & 15); + BlockState fromBlock = get.getBlock(pos.x() & 15, pos.y(), pos.z() & 15); + BlockState toBlock = set.getBlock(pos.x() & 15, pos.y(), pos.z() & 15); if (fromBlock != toBlock || tilesTo.containsKey(pos)) { - addTileRemove(MainUtil.setPosition(entry.getValue(), entry.getKey().getX(), entry.getKey().getY(), - entry.getKey().getZ())); + addTileRemove(NbtUtils.withPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(), + entry.getKey().z() + )); } } } if (!tilesTo.isEmpty()) { - for (Map.Entry entry : tilesTo.entrySet()) { + for (Map.Entry entry : tilesTo.entrySet()) { BlockVector3 pos = entry.getKey(); - addTileCreate(MainUtil.setPosition(entry.getValue(), pos.getX() + bx, pos.getY(), pos.getZ() + bz)); + addTileCreate(NbtUtils.withPosition(entry.getValue(), pos.x() + bx, pos.y(), pos.z() + bz)); } } Set entRemoves = set.getEntityRemoves(); if (!entRemoves.isEmpty()) { for (UUID uuid : entRemoves) { - CompoundTag found = get.getEntity(uuid); + FaweCompoundTag found = get.entity(uuid); if (found != null) { addEntityRemove(found); } } } - Set ents = set.getEntities(); + Collection ents = set.entities(); if (!ents.isEmpty()) { - for (CompoundTag tag : ents) { + for (FaweCompoundTag tag : ents) { addEntityCreate(tag); } } @@ -179,14 +185,14 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { for (int z = 0; z < 16; z++) { int zz = z + bz; for (int x = 0; x < 16; x++, index++) { - int xx = bx + x; - int from = blocksGet[index]; - if (from == BlockTypesCache.ReservedIDs.__RESERVED__) { - from = BlockTypesCache.ReservedIDs.AIR; - } - final int combinedFrom = from; final int combinedTo = blocksSet[index]; if (combinedTo != BlockTypesCache.ReservedIDs.__RESERVED__) { + int xx = bx + x; + int from = blocksGet[index]; + if (from == BlockTypesCache.ReservedIDs.__RESERVED__) { + from = BlockTypesCache.ReservedIDs.AIR; + } + final int combinedFrom = from; add(xx, yy, zz, combinedFrom, combinedTo); } } @@ -203,9 +209,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { BiomeType[] biomeSection = biomes[layer - set.getMinSectionPosition()]; int index = 0; int yy = layer << 4; - for (int y = 0; y < 16; y+= 4) { - for (int z = 0; z < 16; z+= 4) { - for (int x = 0; x < 16; x+= 4, index++) { + for (int y = 0; y < 16; y += 4) { + for (int z = 0; z < 16; z += 4) { + for (int x = 0; x < 16; x += 4, index++) { BiomeType newBiome = biomeSection[index]; if (newBiome != null) { BiomeType oldBiome = get.getBiomeType(x, yy + y, z); @@ -236,13 +242,62 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { return ProcessorScope.READING_SET_BLOCKS; } - public abstract void addTileCreate(CompoundTag tag); + @Deprecated(forRemoval = true, since = "2.11.2") + public void addTileCreate(CompoundTag tag) { + addTileCreate(adapt(tag)); + } - public abstract void addTileRemove(CompoundTag tag); + @SuppressWarnings({"deprecation"}) + private static @Nonnull FaweCompoundTag adapt(CompoundTag tag) { + return FaweCompoundTag.of(tag.toLinTag()); + } - public abstract void addEntityRemove(CompoundTag tag); + /** + * Creates a tile/block entity create change to this change set. + * + * @param tag the tile/block entity to add. + * @since 2.11.2 + */ + public abstract void addTileCreate(FaweCompoundTag tag); - public abstract void addEntityCreate(CompoundTag tag); + @Deprecated(forRemoval = true, since = "2.11.2") + public void addTileRemove(CompoundTag tag) { + addTileRemove(adapt(tag)); + } + + /** + * Creates a tile/block entity remove change to this change set. + * + * @param tag the tile/block entity to remove. + * @since 2.11.2 + */ + public abstract void addTileRemove(FaweCompoundTag tag); + + @Deprecated(forRemoval = true, since = "2.11.2") + public void addEntityRemove(CompoundTag tag) { + addEntityRemove(adapt(tag)); + } + + /** + * Creates an entity remove change to this change set. + * + * @param tag the entity to remove. + * @since 2.11.2 + */ + public abstract void addEntityRemove(FaweCompoundTag tag); + + @Deprecated(forRemoval = true, since = "2.11.2") + public void addEntityCreate(CompoundTag tag) { + addEntityCreate(adapt(tag)); + } + + /** + * Creates an entity create change to this change set. + * + * @param tag the entity to add. + * @since 2.11.2 + */ + public abstract void addEntityCreate(FaweCompoundTag tag); public abstract void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to); @@ -250,6 +305,13 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { return getIterator(redo); } + /** + * {@return a coordinator to exchange sets of changes between a producer and a consumer} + * @since 2.11.2 + */ + @ApiStatus.Internal + public abstract ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir); + public abstract Iterator getIterator(boolean redo); public EditSession toEditSession(Actor actor) { @@ -257,12 +319,14 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { } public EditSession toEditSession(Actor actor, Region[] regions) { - EditSessionBuilder builder = WorldEdit.getInstance().newEditSessionBuilder().world(getWorld()).actor(actor). - fastMode(false).checkMemory(false).changeSet(this).limitUnlimited(); - if (regions != null) { - builder.allowedRegions(regions); - } else { - builder.allowedRegionsEverywhere(); + EditSessionBuilder builder = WorldEdit.getInstance().newEditSessionBuilder().world(world) + .checkMemory(false) + .changeSetNull() + .fastMode(false) + .limitUnprocessed(actor) + .actor(actor); + if (!actor.getLimit().RESTRICT_HISTORY_TO_REGIONS) { + builder = builder.allowedRegionsEverywhere(); } EditSession editSession = builder.build(); editSession.setSize(1); @@ -270,13 +334,15 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { } public void add(EntityCreate change) { - CompoundTag tag = change.state.getNbtData(); - addEntityCreate(MainUtil.setEntityInfo(tag, change.getEntity())); + LinCompoundTag tag = change.state.getNbt(); + assert tag != null; + addEntityCreate(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity()))); } public void add(EntityRemove change) { - CompoundTag tag = change.state.getNbtData(); - addEntityRemove(MainUtil.setEntityInfo(tag, change.getEntity())); + LinCompoundTag tag = change.state.getNbt(); + assert tag != null; + addEntityRemove(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity()))); } @Override @@ -294,9 +360,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { public void add(BlockChange change) { try { - BlockVector3 loc = change.getPosition(); - BaseBlock from = change.getPrevious(); - BaseBlock to = change.getCurrent(); + BlockVector3 loc = change.position(); + BaseBlock from = change.previous(); + BaseBlock to = change.current(); add(loc, from, to); } catch (Exception e) { LOGGER.catching(e); @@ -304,43 +370,40 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { } public boolean isEmpty() { - return queue.isEmpty() && workerSemaphore.availablePermits() == 1 && size() == 0; + return queue.isEmpty() && workerSemaphore.availablePermits() == 1 && longSize() == 0; } public void add(BlockVector3 loc, BaseBlock from, BaseBlock to) { - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); + int x = loc.x(); + int y = loc.y(); + int z = loc.z(); add(x, y, z, from, to); } public void add(int x, int y, int z, BaseBlock from, BaseBlock to) { try { - if (from.hasNbtData()) { - CompoundTag nbt = from.getNbtData(); - assert nbt != null; - addTileRemove(MainUtil.setPosition(nbt, x, y, z)); + LinCompoundTag nbt = from.getNbt(); + if (nbt != null) { + addTileRemove(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } - if (to.hasNbtData()) { - CompoundTag nbt = to.getNbtData(); - assert nbt != null; - addTileCreate(MainUtil.setPosition(nbt, x, y, z)); + nbt = to.getNbt(); + if (nbt != null) { + addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } int combinedFrom = from.getOrdinal(); int combinedTo = to.getOrdinal(); add(x, y, z, combinedFrom, combinedTo); } catch (Exception e) { - e.printStackTrace(); + LOGGER.catching(e); } } public void add(int x, int y, int z, int combinedFrom, BaseBlock to) { try { - if (to.hasNbtData()) { - CompoundTag nbt = to.getNbtData(); - assert nbt != null; - addTileCreate(MainUtil.setPosition(nbt, x, y, z)); + LinCompoundTag nbt = to.getNbt(); + if (nbt != null) { + addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } int combinedTo = to.getInternalId(); add(x, y, z, combinedFrom, combinedTo); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java index 195a5fdbd..e84888848 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java @@ -1,6 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -46,26 +46,6 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { parent.flush(); } - @Override - public void addTileCreate(CompoundTag tag) { - parent.addTileCreate(tag); - } - - @Override - public void addTileRemove(CompoundTag tag) { - parent.addTileRemove(tag); - } - - @Override - public void addEntityRemove(CompoundTag tag) { - parent.addEntityRemove(tag); - } - - @Override - public void addEntityCreate(CompoundTag tag) { - parent.addEntityCreate(tag); - } - @Override public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { parent.addBiomeChange(x, y, z, from, to); @@ -76,6 +56,11 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { return parent.getIterator(blockBag, mode, redo); } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) { + return parent.getCoordinatedChanges(blockBag, mode, dir); + } + @Override public Iterator getIterator(boolean redo) { return parent.getIterator(redo); @@ -141,6 +126,26 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { return parent.forwardIterator(); } + @Override + public void addTileCreate(final FaweCompoundTag tag) { + parent.addTileCreate(tag); + } + + @Override + public void addTileRemove(final FaweCompoundTag tag) { + parent.addTileRemove(tag); + } + + @Override + public void addEntityRemove(final FaweCompoundTag tag) { + parent.addEntityRemove(tag); + } + + @Override + public void addEntityCreate(final FaweCompoundTag tag) { + parent.addEntityCreate(tag); + } + @Override public void close() throws IOException { parent.close(); @@ -176,6 +181,11 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { return parent.size(); } + @Override + public long longSize() { + return parent.longSize(); + } + @Override public void delete() { parent.delete(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java index 22833d3b5..8c65be084 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java @@ -1,8 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; import com.fastasyncworldedit.core.FaweCache; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagException; import com.sk89q.worldedit.extent.inventory.UnplaceableBlockException; @@ -68,9 +66,9 @@ public class BlockBagChangeSet extends AbstractDelegateChangeSet { @Override public void add(BlockVector3 loc, BaseBlock from, BaseBlock to) { - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); + int x = loc.x(); + int y = loc.y(); + int z = loc.z(); add(x, y, z, from, to); } @@ -109,13 +107,4 @@ public class BlockBagChangeSet extends AbstractDelegateChangeSet { super.add(x, y, z, combinedFrom, combinedTo); } - @Override - public void addTileCreate(CompoundTag nbt) { - if (nbt.containsKey("items")) { - Map map = new HashMap<>(nbt.getValue()); - map.remove("items"); - } - super.addTileCreate(nbt); - } - } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java new file mode 100644 index 000000000..3c020d422 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java @@ -0,0 +1,53 @@ +package com.fastasyncworldedit.core.history.changeset; + +import com.sk89q.worldedit.history.change.Change; +import org.jetbrains.annotations.ApiStatus; + +import java.util.concurrent.Exchanger; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.BiConsumer; + +/** + * @since 2.11.2 + */ +@ApiStatus.Internal +public class ChangeExchangeCoordinator implements AutoCloseable { + + private static final Thread.Builder.OfVirtual UNDO_VIRTUAL_THREAD_BUILDER = Thread.ofVirtual() + .name("FAWE undo", 0); + private final Exchanger exchanger; + private final BiConsumer, Change[]> runnerTask; + private boolean started = false; + private Thread runner; + + public ChangeExchangeCoordinator(BiConsumer, Change[]> runner) { + this.runnerTask = runner; + this.exchanger = new Exchanger<>(); + } + + public Change[] take(Change[] consumed) { + if (!this.started) { + this.started = true; + final int length = consumed.length; + this.runner = UNDO_VIRTUAL_THREAD_BUILDER + .start(() -> this.runnerTask.accept(this.exchanger, new Change[length])); + } + try { + // Allow a reasonable timeout in case of weirdness + return exchanger.exchange(consumed, 30, TimeUnit.SECONDS); + } catch (InterruptedException | TimeoutException e) { + this.runner.interrupt(); + Thread.currentThread().interrupt(); + return null; + } + } + + @Override + public void close() { + if (this.runner != null) { + this.runner.interrupt(); + } + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java index c2ae362ae..f8ff1956f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.history.changeset; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.history.change.ChangePopulator; import com.fastasyncworldedit.core.history.change.MutableBiomeChange; import com.fastasyncworldedit.core.history.change.MutableBlockChange; import com.fastasyncworldedit.core.history.change.MutableEntityChange; @@ -9,6 +10,7 @@ import com.fastasyncworldedit.core.history.change.MutableTileChange; import com.fastasyncworldedit.core.internal.exception.FaweSmallEditUnsupportedException; import com.fastasyncworldedit.core.internal.io.FaweInputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.jnbt.CompoundTag; @@ -20,14 +22,22 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayDeque; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.Exchanger; +import java.util.function.BiConsumer; /** * FAWE stream ChangeSet offering support for extended-height worlds @@ -35,11 +45,18 @@ import java.util.NoSuchElementException; public abstract class FaweStreamChangeSet extends AbstractChangeSet { public static final int HEADER_SIZE = 9; - private static final int version = 1; + private static final int VERSION = 2; + // equivalent to Short#MIN_VALUE three times stored with [(x) & 0xff, ((rx) >> 8) & 0xff] + private static final byte[] MAGIC_NEW_RELATIVE = new byte[]{0, (byte) 128, 0, (byte) 128, 0, (byte) 128}; private int mode; private final int compression; private final int minY; + protected long blockSize; + private int originX; + private int originZ; + private int version; + protected FaweStreamIdDelegate idDel; protected FaweStreamPositionDelegate posDel; @@ -167,7 +184,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { @Override public int readX(FaweInputStream in) throws IOException { in.readFully(buffer); - return lx = lx + ((((buffer[1] & 0xFF) + ((MathMan.unpair16x(buffer[3])) << 8)) << 20) >> 20); + return lx = lx + ((((buffer[1] & 0xFF) | ((MathMan.unpair16x(buffer[3])) << 8)) << 20) >> 20); } @Override @@ -177,7 +194,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { @Override public int readZ(FaweInputStream in) throws IOException { - return lz = lz + ((((buffer[2] & 0xFF) + ((MathMan.unpair16y(buffer[3])) << 8)) << 20) >> 20); + return lz = lz + ((((buffer[2] & 0xFF) | ((MathMan.unpair16y(buffer[3])) << 8)) << 20) >> 20); } }; } else { @@ -192,6 +209,20 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { int rx = -lx + (lx = x); int ry = -ly + (ly = y); int rz = -lz + (lz = z); + // Use LE/GE to ensure we don't accidentally write MAGIC_NEW_RELATIVE + if (rx >= Short.MAX_VALUE || rz >= Short.MAX_VALUE || rx <= Short.MIN_VALUE || rz <= Short.MIN_VALUE) { + stream.write(MAGIC_NEW_RELATIVE); + stream.write((byte) (x >> 24)); + stream.write((byte) (x >> 16)); + stream.write((byte) (x >> 8)); + stream.write((byte) (x)); + stream.write((byte) (z >> 24)); + stream.write((byte) (z >> 16)); + stream.write((byte) (z >> 8)); + stream.write((byte) (z)); + rx = 0; + rz = 0; + } stream.write((rx) & 0xff); stream.write(((rx) >> 8) & 0xff); stream.write((rz) & 0xff); @@ -203,17 +234,23 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { @Override public int readX(FaweInputStream is) throws IOException { is.readFully(buffer); - return lx = (lx + (buffer[0] & 0xFF) + (buffer[1] << 8)); + // Don't break reading version 1 history (just in case) + if (version == 2 && Arrays.equals(buffer, MAGIC_NEW_RELATIVE)) { + lx = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()); + lz = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()); + is.readFully(buffer); + } + return lx = lx + ((buffer[0] & 0xFF) | (buffer[1] << 8)); } @Override public int readY(FaweInputStream is) throws IOException { - return ly = (ly + (buffer[4] & 0xFF) + (buffer[5] << 8)); + return ly = ly + ((buffer[4] & 0xFF) | (buffer[5]) << 8); } @Override public int readZ(FaweInputStream is) throws IOException { - return lz = (lz + (buffer[2] & 0xFF) + (buffer[3] << 8)); + return lz = lz + ((buffer[2] & 0xFF) | (buffer[3]) << 8); } }; } @@ -222,7 +259,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void writeHeader(OutputStream os, int x, int y, int z) throws IOException { os.write(mode); // Allows for version detection of history in case of changes to format. - os.write(version); + os.write(VERSION); setOrigin(x, z); os.write((byte) (x >> 24)); os.write((byte) (x >> 16)); @@ -238,8 +275,8 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void readHeader(InputStream is) throws IOException { // skip mode int mode = is.read(); - int version = is.read(); - if (version != FaweStreamChangeSet.version) { + version = is.read(); + if (version != 1 && version != VERSION) { // version 1 is fine throw new UnsupportedOperationException(String.format("Version %s history not supported!", version)); } // origin @@ -266,12 +303,17 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } @Override - public int size() { + public long longSize() { // Flush so we can accurately get the size flush(); return blockSize; } + @Override + public int size() { + return (int) longSize(); + } + public abstract int getCompressedSize(); public abstract long getSizeInMemory(); @@ -304,11 +346,6 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public abstract NBTInputStream getTileRemoveIS() throws IOException; - protected int blockSize; - - private int originX; - private int originZ; - public void setOrigin(int x, int z) { originX = x; originZ = z; @@ -362,56 +399,44 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } @Override - public void addTileCreate(CompoundTag tag) { - if (tag == null) { - return; - } + public void addTileCreate(final FaweCompoundTag tag) { blockSize++; try { NBTOutputStream nbtos = getTileCreateOS(); - nbtos.writeTag(tag); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addTileRemove(CompoundTag tag) { - if (tag == null) { - return; - } + public void addTileRemove(final FaweCompoundTag tag) { blockSize++; try { NBTOutputStream nbtos = getTileRemoveOS(); - nbtos.writeTag(tag); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addEntityRemove(CompoundTag tag) { - if (tag == null) { - return; - } + public void addEntityRemove(final FaweCompoundTag tag) { blockSize++; try { NBTOutputStream nbtos = getEntityRemoveOS(); - nbtos.writeTag(tag); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addEntityCreate(CompoundTag tag) { - if (tag == null) { - return; - } + public void addEntityCreate(final FaweCompoundTag tag) { blockSize++; try { NBTOutputStream nbtos = getEntityCreateOS(); - nbtos.writeTag(tag); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } @@ -683,6 +708,286 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir) { + try { + return coordinatedChanges(blockBag, mode, dir); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private ChangeExchangeCoordinator coordinatedChanges(final BlockBag blockBag, final int mode, boolean dir) throws IOException { + close(); + var tileCreate = tileChangePopulator(getTileCreateIS(), true); + var tileRemove = tileChangePopulator(getTileRemoveIS(), false); + + var entityCreate = entityChangePopulator(getEntityCreateIS(), true); + var entityRemove = entityChangePopulator(getEntityRemoveIS(), false); + + var blockChange = blockBag != null && mode > 0 ? fullBlockChangePopulator(blockBag, mode, dir) : blockChangePopulator(dir); + + var biomeChange = biomeChangePopulator(dir); + + Queue> populators = new ArrayDeque<>(List.of( + tileCreate, + tileRemove, + entityCreate, + entityRemove, + blockChange, + biomeChange + )); + BiConsumer, Change[]> task = (exchanger, array) -> { + while (fillArray(array, populators)) { + try { + array = exchanger.exchange(array); + } catch (InterruptedException e) { + return; + } + } + }; + return new ChangeExchangeCoordinator(task); + } + + private boolean fillArray(Change[] changes, Queue> populators) { + ChangePopulator populator = populators.peek(); + if (populator == null) { + return false; + } + for (int i = 0; i < changes.length; i++) { + Change change = changes[i]; + do { + change = populator.updateOrCreate(change); + if (change == null) { + populators.remove(); + populator = populators.peek(); + if (populator == null) { + changes[i] = null; // mark end + return true; // still needs to consume the elements of the current round + } + } else { + break; + } + } while (true); + changes[i] = change; + } + return true; + } + + private static abstract class CompoundTagPopulator implements ChangePopulator { + private final NBTInputStream inputStream; + + private CompoundTagPopulator(final NBTInputStream stream) { + inputStream = stream; + } + + @Override + public @Nullable C populate(final @NotNull C change) { + try { + write(change, (CompoundTag) inputStream.readTag()); + return change; + } catch (Exception ignored) { + } + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + protected abstract void write(C change, CompoundTag tag); + } + + private ChangePopulator tileChangePopulator(NBTInputStream is, boolean create) { + if (is == null) { + return ChangePopulator.empty(); + } + class Populator extends CompoundTagPopulator { + + private Populator() { + super(is); + } + + @Override + public @NotNull MutableTileChange create() { + return new MutableTileChange(null, create); + } + + @Override + protected void write(final MutableTileChange change, final CompoundTag tag) { + change.tag = tag; + change.create = create; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableTileChange; + } + + } + return new Populator(); + } + private ChangePopulator entityChangePopulator(NBTInputStream is, boolean create) { + if (is == null) { + return ChangePopulator.empty(); + } + class Populator extends CompoundTagPopulator { + + private Populator() { + super(is); + } + + @Override + public @NotNull MutableEntityChange create() { + return new MutableEntityChange(null, create); + } + + @Override + protected void write(final MutableEntityChange change, final CompoundTag tag) { + change.tag = tag; + change.create = create; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableTileChange; + } + + } + return new Populator(); + } + + private ChangePopulator fullBlockChangePopulator(BlockBag blockBag, int mode, boolean dir) throws + IOException { + final FaweInputStream is = getBlockIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableFullBlockChange create() { + return new MutableFullBlockChange(blockBag, mode, dir); + } + + @Override + public @Nullable MutableFullBlockChange populate(@NotNull final MutableFullBlockChange change) { + try { + change.x = posDel.readX(is) + originX; + change.y = posDel.readY(is); + change.z = posDel.readZ(is) + originZ; + idDel.readCombined(is, change); + return change; + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableFullBlockChange; + } + + } + return new Populator(); + + } + + private ChangePopulator blockChangePopulator(boolean dir) throws IOException { + final FaweInputStream is = getBlockIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableBlockChange create() { + return new MutableBlockChange(0, 0, 0, BlockTypes.AIR.getInternalId()); + } + + @Override + public @Nullable MutableBlockChange populate(@NotNull final MutableBlockChange change) { + try { + change.x = posDel.readX(is) + originX; + change.y = posDel.readY(is); + change.z = posDel.readZ(is) + originZ; + idDel.readCombined(is, change, dir); + return change; + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableBlockChange; + } + + } + return new Populator(); + } + + private ChangePopulator biomeChangePopulator(boolean dir) throws IOException { + final FaweInputStream is = getBiomeIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableBiomeChange create() { + return new MutableBiomeChange(); + } + + @Override + public @Nullable MutableBiomeChange populate(@NotNull final MutableBiomeChange change) { + try { + int int1 = is.read(); + if (int1 != -1) { + int x = ((int1 << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2; + int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2; + int y = (is.read() - 128) << 2; + int from = is.readVarInt(); + int to = is.readVarInt(); + change.setBiome(x, y, z, from, to); + return change; + } + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableBiomeChange; + } + + } + return new Populator(); + } + @Override public Iterator getIterator(final boolean dir) { try { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java index dd4fddf1a..99711b6cc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java @@ -1,6 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; @@ -25,22 +25,22 @@ public class NullChangeSet extends AbstractChangeSet { } @Override - public final void addTileCreate(CompoundTag tag) { + public void addTileCreate(final FaweCompoundTag tag) { } @Override - public final void addTileRemove(CompoundTag tag) { + public void addTileRemove(final FaweCompoundTag tag) { } @Override - public final void addEntityRemove(CompoundTag tag) { + public void addEntityRemove(final FaweCompoundTag tag) { } @Override - public final void addEntityCreate(CompoundTag tag) { + public void addEntityCreate(final FaweCompoundTag tag) { } @@ -54,6 +54,17 @@ public class NullChangeSet extends AbstractChangeSet { return getIterator(redo); } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) { + return new ChangeExchangeCoordinator(((exchanger, changes) -> { + try { + exchanger.exchange(null); + } catch (InterruptedException ignored) { + Thread.currentThread().interrupt(); + } + })); + } + @Override public final Iterator getIterator(boolean undo) { return Collections.emptyIterator(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/io/VarIntStreamIterator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/io/VarIntStreamIterator.java new file mode 100644 index 000000000..17f4b9f0a --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/io/VarIntStreamIterator.java @@ -0,0 +1,70 @@ +package com.fastasyncworldedit.core.internal.io; + +import java.io.IOException; +import java.io.InputStream; +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +/** + * Basically {@link com.sk89q.worldedit.internal.util.VarIntIterator} but backed by {@link java.io.InputStream} + */ +public class VarIntStreamIterator implements PrimitiveIterator.OfInt { + + private final InputStream parent; + private final int limit; + private int index; + private boolean hasNextInt; + private int nextInt; + + public VarIntStreamIterator(final InputStream parent, int limit) { + this.parent = parent; + this.limit = limit; + } + + @Override + public boolean hasNext() { + if (hasNextInt) { + return true; + } + if (index >= limit) { + return false; + } + + try { + nextInt = readNextInt(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return hasNextInt = true; + } + + @Override + public int nextInt() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + hasNextInt = false; + return nextInt; + } + + + private int readNextInt() throws IOException { + int value = 0; + for (int bitsRead = 0; ; bitsRead += 7) { + if (index >= limit) { + throw new IllegalStateException("Ran out of bytes while reading VarInt (probably corrupted data)"); + } + byte next = (byte) this.parent.read(); + index++; + value |= (next & 0x7F) << bitsRead; + if (bitsRead > 7 * 5) { + throw new IllegalStateException("VarInt too big (probably corrupted data)"); + } + if ((next & 0x80) == 0) { + break; + } + } + return value; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java new file mode 100644 index 000000000..eefdc1929 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java @@ -0,0 +1,117 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; +import com.fastasyncworldedit.core.function.mask.InverseMask; +import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask; +import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; +import com.sk89q.worldedit.function.mask.InverseSingleBlockStateMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; + +import javax.annotation.Nullable; + +public class SimdSupport { + + private static final boolean VECTOR_API_PRESENT; + + static { + boolean vectorApiPresent = false; + try { + Class.forName("jdk.incubator.vector.Vector"); + vectorApiPresent = true; + } catch (ClassNotFoundException ignored) { + } + VECTOR_API_PRESENT = vectorApiPresent; + if (!VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API) { + LogManagerCompat.getLogger() + .warn("FAWE use-vector-api is enabled but --add-modules=jdk.incubator.vector is not set."); + } + } + + public static boolean useVectorApi() { + return VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API; + } + + public static @Nullable VectorizedMask vectorizedTargetMask(Mask mask) { + if (!useVectorApi()) { + return null; + } + return switch (mask) { + case SingleBlockStateMask single -> vectorizedTargetMask(single.getBlockState().getOrdinalChar()); + case InverseSingleBlockStateMask inverse -> vectorizedTargetMaskInverse(inverse.getBlockState().getOrdinalChar()); + case ExistingBlockMask ignored -> vectorizedTargetMaskNonAir(); + case InverseMask inverse -> { + final VectorizedMask base = vectorizedTargetMask(inverse.inverse()); + if (base == null) { + yield null; + } + yield (set, get) -> base.compareVector(set, get).not(); + } + default -> null; + }; + } + + private static VectorizedMask vectorizedTargetMaskNonAir() { + // everything > VOID_AIR is not air + return (set, get) -> get.compare(VectorOperators.UNSIGNED_GT, BlockTypesCache.ReservedIDs.VOID_AIR); + } + + private static VectorizedMask vectorizedTargetMask(char ordinal) { + return (set, get) -> get.compare(VectorOperators.EQ, (short) ordinal); + } + + private static VectorizedMask vectorizedTargetMaskInverse(char ordinal) { + return (set, get) -> get.compare(VectorOperators.NE, (short) ordinal); + } + + public static @Nullable VectorizedFilter vectorizedPattern(Pattern pattern) { + if (!useVectorApi()) { + return null; + } + return switch (pattern) { + case BaseBlock block -> { + if (block.getNbtReference() == null) { + yield new VectorizedPattern<>(block, block.getOrdinalChar()); + } + yield null; + } + case BlockStateHolder blockStateHolder -> new VectorizedPattern<>( + blockStateHolder, + blockStateHolder.getOrdinalChar() + ); + default -> null; + }; + } + + private static final class VectorizedPattern extends DelegateFilter implements VectorizedFilter { + + private final char ordinal; + + public VectorizedPattern(final T parent, char ordinal) { + super(parent); + this.ordinal = ordinal; + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set, VectorMask mask) { + // only change the lanes the mask dictates us to change, keep the rest + return set.blend(ShortVector.broadcast(ShortVector.SPECIES_PREFERRED, ordinal), mask); + } + + @Override + public Filter newInstance(final Filter other) { + return new VectorizedPattern<>(other, ordinal); + } + + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java new file mode 100644 index 000000000..9f557b134 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java @@ -0,0 +1,36 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; +import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.extent.Extent; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; + +public class VectorizedCharFilterBlock extends CharFilterBlock { + + public VectorizedCharFilterBlock(final Extent extent) { + super(extent); + } + + @Override + public synchronized void filter(final Filter filter) { + if (!(filter instanceof VectorizedFilter vecFilter)) { + throw new IllegalStateException("Unexpected VectorizedCharFilterBlock " + filter); + } + final VectorSpecies species = ShortVector.SPECIES_PREFERRED; + // TODO can we avoid eager initSet? + initSet(); // set array is null before + char[] setArr = this.setArr; + assert setArr != null; + char[] getArr = this.getArr; + // assume setArr.length == getArr.length == 4096 + VectorMask affectAll = species.maskAll(true); + for (int i = 0; i < 4096; i += species.length()) { + ShortVector set = ShortVector.fromCharArray(species, setArr, i); + ShortVector get = ShortVector.fromCharArray(species, getArr, i); + ShortVector res = vecFilter.applyVector(get, set, affectAll); + res.intoCharArray(setArr, i); + } + } +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java new file mode 100644 index 000000000..b0801fcd0 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java @@ -0,0 +1,19 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.queue.Filter; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; + +public interface VectorizedFilter extends Filter { + + /** + * Applies a filter to a vector pair of get and set. + * + * @param get the get vector + * @param set the set vector + * @param mask the mask with the lanes set to true which should be affected by the filter + * @return the resulting set vector. + */ + ShortVector applyVector(ShortVector get, ShortVector set, VectorMask mask); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java new file mode 100644 index 000000000..a6fd18b48 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java @@ -0,0 +1,53 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; + +public interface VectorizedMask { + + default void processChunks(IChunk chunk, IChunkGet get, IChunkSet set) { + for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { + final char[] sectionSet = set.loadIfPresent(layer); + if (sectionSet == null) { + continue; + } + final char[] sectionGet = get.load(layer); + processSection(layer, sectionSet, sectionGet); + } + } + + default void processSection(int layer, char[] set, char[] get) { + final VectorSpecies species = ShortVector.SPECIES_PREFERRED; + // assume that set.length % species.elementSize() == 0 + for (int i = 0; i < set.length; i += species.length()) { + ShortVector vectorSet = ShortVector.fromCharArray(species, set, i); + ShortVector vectorGet = ShortVector.fromCharArray(species, get, i); + vectorSet = processVector(vectorSet, vectorGet); + vectorSet.intoCharArray(set, i); + } + } + + /** + * {@return the set vector with all lanes that do not match this mask set to 0} + * + * @param set the set vector + * @param get the get vector + */ + default ShortVector processVector(ShortVector set, ShortVector get) { + return set.blend(BlockTypesCache.ReservedIDs.__RESERVED__, compareVector(set, get).not()); + } + + /** + * {@return a mask with all lanes set that match this mask} + * + * @param set the set vector + * @param get the get vector + */ + VectorMask compareVector(ShortVector set, ShortVector get); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedCompoundTag.java index 85bdddf09..efed01376 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedCompoundTag.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedCompoundTag.java @@ -19,7 +19,7 @@ public abstract class CompressedCompoundTag extends CompoundTag { } @Override - public Map getValue() { + public Map> getValue() { if (in != null) { decompress(); } @@ -36,8 +36,8 @@ public abstract class CompressedCompoundTag extends CompoundTag { try (NBTInputStream nbtIn = new NBTInputStream(adapt(in))) { in = null; CompoundTag tag = (CompoundTag) nbtIn.readTag(); - Map value = tag.getValue(); - Map raw = super.getValue(); + Map> value = tag.getValue(); + Map> raw = super.getValue(); raw.putAll(value); } catch (IOException e) { throw new RuntimeException(e); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedSchematicTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedSchematicTag.java index e622b1501..3c569f913 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedSchematicTag.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/CompressedSchematicTag.java @@ -1,6 +1,6 @@ package com.fastasyncworldedit.core.jnbt; -import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriterV2; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.internal.io.FastByteArraysInputStream; import com.sk89q.jnbt.NBTOutputStream; @@ -21,7 +21,7 @@ public class CompressedSchematicTag extends CompressedCompoundTag { FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream(); try (LZ4BlockOutputStream lz4out = new LZ4BlockOutputStream(blocksOut)) { NBTOutputStream nbtOut = new NBTOutputStream(lz4out); - new FastSchematicWriter(nbtOut).write(getSource()); + new FastSchematicWriterV2(nbtOut).write(getSource()); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/JSON2NBT.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/JSON2NBT.java index 8b942895d..6cdef3dda 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/JSON2NBT.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/JSON2NBT.java @@ -17,7 +17,6 @@ import com.sk89q.jnbt.Tag; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.Stack; import java.util.regex.Pattern; @@ -409,7 +408,7 @@ public class JSON2NBT { } public Tag parse() throws NBTException { - HashMap map = new HashMap<>(); + HashMap> map = new HashMap<>(); for (Any JSON2NBT$any : this.tagList) { map.put(JSON2NBT$any.json, JSON2NBT$any.parse()); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/NumberTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/NumberTag.java index db1984bb3..5931069c6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/NumberTag.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/jnbt/NumberTag.java @@ -1,11 +1,16 @@ package com.fastasyncworldedit.core.jnbt; import com.sk89q.jnbt.Tag; +import org.enginehub.linbus.tree.LinTag; /** * A numerical {@link Tag} */ -public abstract class NumberTag extends Tag { +public abstract class NumberTag> extends Tag { + + protected NumberTag(LT linTag) { + super(linTag); + } @Override public abstract Number getValue(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java index 00a47178c..0dde6baac 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java @@ -1,26 +1,36 @@ package com.fastasyncworldedit.core.limit; import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.configuration.Settings; import java.util.Collections; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public class FaweLimit { public int MAX_ACTIONS = 0; - public long MAX_CHANGES = 0; - public int MAX_FAILS = 0; - public long MAX_CHECKS = 0; - public int MAX_ITERATIONS = 0; - public int MAX_BLOCKSTATES = 0; - public int MAX_ENTITIES = 0; + public AtomicLong MAX_CHANGES = new AtomicLong(); + public AtomicInteger MAX_FAILS = new AtomicInteger(); + public AtomicLong MAX_CHECKS = new AtomicLong(); + public AtomicInteger MAX_ITERATIONS = new AtomicInteger(); + public AtomicInteger MAX_BLOCKSTATES = new AtomicInteger(); + public AtomicInteger MAX_ENTITIES = new AtomicInteger(); public int MAX_HISTORY = 0; + public int SCHEM_FILE_SIZE_LIMIT = 0; + public int SCHEM_FILE_NUM_LIMIT = 0; public int MAX_EXPRESSION_MS = 0; + public int MAX_RADIUS = 0; + public int MAX_SUPER_PICKAXE_SIZE = 0; + public int MAX_BRUSH_RADIUS = 0; + public int MAX_BUTCHER_RADIUS = 0; public int INVENTORY_MODE = Integer.MAX_VALUE; public int SPEED_REDUCTION = Integer.MAX_VALUE; public boolean FAST_PLACEMENT = false; public boolean CONFIRM_LARGE = true; public boolean RESTRICT_HISTORY_TO_REGIONS = true; + public boolean ALLOW_LEGACY = true; public Set STRIP_NBT = null; public boolean UNIVERSAL_DISALLOWED_BLOCKS = true; public Set DISALLOWED_BLOCKS = null; @@ -104,158 +114,215 @@ public class FaweLimit { MAX.SPEED_REDUCTION = 0; MAX.INVENTORY_MODE = 0; MAX.MAX_ACTIONS = 1; - MAX.MAX_CHANGES = Long.MAX_VALUE; - MAX.MAX_FAILS = Integer.MAX_VALUE; - MAX.MAX_CHECKS = Long.MAX_VALUE; - MAX.MAX_ITERATIONS = Integer.MAX_VALUE; - MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE; - MAX.MAX_ENTITIES = Integer.MAX_VALUE; + MAX.MAX_CHANGES = new AtomicLong(Long.MAX_VALUE); + MAX.MAX_FAILS = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_CHECKS = new AtomicLong(Long.MAX_VALUE); + MAX.MAX_ITERATIONS = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_BLOCKSTATES = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_ENTITIES = new AtomicInteger(Integer.MAX_VALUE); MAX.MAX_HISTORY = Integer.MAX_VALUE; + MAX.SCHEM_FILE_NUM_LIMIT = Integer.MAX_VALUE; + MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE; MAX.MAX_EXPRESSION_MS = 50; MAX.FAST_PLACEMENT = true; - MAX.CONFIRM_LARGE = true; + MAX.CONFIRM_LARGE = + Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS; MAX.RESTRICT_HISTORY_TO_REGIONS = false; MAX.STRIP_NBT = Collections.emptySet(); MAX.UNIVERSAL_DISALLOWED_BLOCKS = false; + MAX.ALLOW_LEGACY = true; MAX.DISALLOWED_BLOCKS = Collections.emptySet(); MAX.REMAP_PROPERTIES = Collections.emptySet(); + MAX.MAX_RADIUS = Integer.MAX_VALUE; + MAX.MAX_SUPER_PICKAXE_SIZE = Integer.MAX_VALUE; + MAX.MAX_BRUSH_RADIUS = Integer.MAX_VALUE; + MAX.MAX_BUTCHER_RADIUS = Integer.MAX_VALUE; } public boolean MAX_CHANGES() { - return MAX_CHANGES-- > 0; + return MAX_CHANGES.decrementAndGet() < 0; } public boolean MAX_FAILS() { - return MAX_FAILS-- > 0; + return MAX_FAILS.decrementAndGet() < 0; } public boolean MAX_CHECKS() { - return MAX_CHECKS-- > 0; + return MAX_CHECKS.decrementAndGet() < 0; } public boolean MAX_ITERATIONS() { - return MAX_ITERATIONS-- > 0; + return MAX_ITERATIONS.decrementAndGet() < 0; } public boolean MAX_BLOCKSTATES() { - return MAX_BLOCKSTATES-- > 0; + return MAX_BLOCKSTATES.decrementAndGet() < 0; } public boolean MAX_ENTITIES() { - return MAX_ENTITIES-- > 0; + return MAX_ENTITIES.decrementAndGet() < 0; } public void THROW_MAX_CHANGES() { - if (MAX_CHANGES-- <= 0) { + if (MAX_CHANGES.decrementAndGet() < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_FAILS() { - if (MAX_FAILS-- <= 0) { - throw FaweCache.MAX_CHECKS; + if (MAX_FAILS.decrementAndGet() < 0) { + throw FaweCache.MAX_FAILS; } } public void THROW_MAX_CHECKS() { - if (MAX_CHECKS-- <= 0) { + if (MAX_CHECKS.decrementAndGet() < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_ITERATIONS() { - if (MAX_ITERATIONS-- <= 0) { + if (MAX_ITERATIONS.decrementAndGet() < 0) { throw FaweCache.MAX_ITERATIONS; } } public void THROW_MAX_BLOCKSTATES() { - if (MAX_BLOCKSTATES-- <= 0) { + if (MAX_BLOCKSTATES.decrementAndGet() < 0) { throw FaweCache.MAX_TILES; } } public void THROW_MAX_ENTITIES() { - if (MAX_ENTITIES-- <= 0) { + if (MAX_ENTITIES.decrementAndGet() < 0) { throw FaweCache.MAX_ENTITIES; } } public void THROW_MAX_CHANGES(int amt) { - if ((MAX_CHANGES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHANGES.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_CHANGES(long amt) { - if ((MAX_CHANGES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHANGES.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_FAILS(int amt) { - if ((MAX_FAILS -= amt) <= 0) { - throw FaweCache.MAX_CHECKS; + if (amt == 0) { + return; + } + if (MAX_FAILS.addAndGet(-amt) < 0) { + throw FaweCache.MAX_FAILS; } } public void THROW_MAX_CHECKS(int amt) { - if ((MAX_CHECKS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHECKS.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_CHECKS(long amt) { - if ((MAX_CHECKS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHECKS.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_ITERATIONS(int amt) { - if ((MAX_ITERATIONS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_ITERATIONS.addAndGet(-amt) < 0) { throw FaweCache.MAX_ITERATIONS; } } public void THROW_MAX_BLOCKSTATES(int amt) { - if ((MAX_BLOCKSTATES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_BLOCKSTATES.addAndGet(-amt) < 0) { throw FaweCache.MAX_TILES; } } public void THROW_MAX_ENTITIES(int amt) { - if ((MAX_ENTITIES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_ENTITIES.addAndGet(-amt) < 0) { throw FaweCache.MAX_ENTITIES; } } public boolean isUnlimited() { - return MAX_CHANGES == Long.MAX_VALUE - && MAX_FAILS == Integer.MAX_VALUE - && MAX_CHECKS == Long.MAX_VALUE - && MAX_ITERATIONS == Integer.MAX_VALUE - && MAX_BLOCKSTATES == Integer.MAX_VALUE - && MAX_ENTITIES == Integer.MAX_VALUE + return MAX_CHANGES.get() == Long.MAX_VALUE + && MAX_FAILS.get() == Integer.MAX_VALUE + && MAX_CHECKS.get() == Long.MAX_VALUE + && MAX_ITERATIONS.get() == Integer.MAX_VALUE + && MAX_BLOCKSTATES.get() == Integer.MAX_VALUE + && MAX_ENTITIES.get() == Integer.MAX_VALUE && MAX_HISTORY == Integer.MAX_VALUE + && SCHEM_FILE_SIZE_LIMIT == Integer.MAX_VALUE + && SCHEM_FILE_NUM_LIMIT == Integer.MAX_VALUE && INVENTORY_MODE == 0 && SPEED_REDUCTION == 0 && FAST_PLACEMENT && !RESTRICT_HISTORY_TO_REGIONS && (STRIP_NBT == null || STRIP_NBT.isEmpty()) // && !UNIVERSAL_DISALLOWED_BLOCKS --> do not include this, it effectively has no relevance + && ALLOW_LEGACY && (DISALLOWED_BLOCKS == null || DISALLOWED_BLOCKS.isEmpty()) - && (REMAP_PROPERTIES == null || REMAP_PROPERTIES.isEmpty()); + && (REMAP_PROPERTIES == null || REMAP_PROPERTIES.isEmpty()) + && MAX_RADIUS == Integer.MAX_VALUE + && MAX_SUPER_PICKAXE_SIZE == Integer.MAX_VALUE + && MAX_BRUSH_RADIUS == Integer.MAX_VALUE + && MAX_BUTCHER_RADIUS == Integer.MAX_VALUE; + } + + /** + * Get an {@link FaweLimit} representing the amount of a limit used from a given "original" limit + * + * @since 2.12.0 + */ + public FaweLimit getLimitUsed(FaweLimit originalLimit) { + FaweLimit newLimit = new FaweLimit(); + newLimit.MAX_CHANGES = new AtomicLong(originalLimit.MAX_CHANGES.get() - this.MAX_CHANGES.get()); + newLimit.MAX_FAILS = new AtomicInteger(originalLimit.MAX_FAILS.get() - this.MAX_FAILS.get()); + newLimit.MAX_CHECKS = new AtomicLong(originalLimit.MAX_CHECKS.get() - this.MAX_CHECKS.get()); + newLimit.MAX_ITERATIONS = new AtomicInteger(originalLimit.MAX_ITERATIONS.get() - this.MAX_ITERATIONS.get()); + newLimit.MAX_BLOCKSTATES = new AtomicInteger(originalLimit.MAX_BLOCKSTATES.get() - this.MAX_BLOCKSTATES.get()); + newLimit.MAX_ENTITIES = new AtomicInteger(originalLimit.MAX_ENTITIES.get() - this.MAX_ENTITIES.get()); + return newLimit; } public void set(FaweLimit limit) { MAX_ACTIONS = limit.MAX_ACTIONS; - MAX_CHANGES = limit.MAX_CHANGES; - MAX_BLOCKSTATES = limit.MAX_BLOCKSTATES; - MAX_CHECKS = limit.MAX_CHECKS; - MAX_ENTITIES = limit.MAX_ENTITIES; - MAX_FAILS = limit.MAX_FAILS; - MAX_ITERATIONS = limit.MAX_ITERATIONS; + MAX_CHANGES.set(limit.MAX_CHANGES.get()); + MAX_FAILS.set(limit.MAX_FAILS.get()); + MAX_CHECKS.set(limit.MAX_CHECKS.get()); + MAX_ITERATIONS.set(limit.MAX_ITERATIONS.get()); + MAX_BLOCKSTATES.set(limit.MAX_BLOCKSTATES.get()); + MAX_ENTITIES.set(limit.MAX_ENTITIES.get()); MAX_HISTORY = limit.MAX_HISTORY; + SCHEM_FILE_NUM_LIMIT = limit.SCHEM_FILE_NUM_LIMIT; + SCHEM_FILE_SIZE_LIMIT = limit.SCHEM_FILE_SIZE_LIMIT; INVENTORY_MODE = limit.INVENTORY_MODE; SPEED_REDUCTION = limit.SPEED_REDUCTION; FAST_PLACEMENT = limit.FAST_PLACEMENT; @@ -263,8 +330,13 @@ public class FaweLimit { RESTRICT_HISTORY_TO_REGIONS = limit.RESTRICT_HISTORY_TO_REGIONS; STRIP_NBT = limit.STRIP_NBT; UNIVERSAL_DISALLOWED_BLOCKS = limit.UNIVERSAL_DISALLOWED_BLOCKS; + ALLOW_LEGACY = limit.ALLOW_LEGACY; DISALLOWED_BLOCKS = limit.DISALLOWED_BLOCKS; REMAP_PROPERTIES = limit.REMAP_PROPERTIES; + MAX_RADIUS = limit.MAX_RADIUS; + MAX_SUPER_PICKAXE_SIZE = limit.MAX_SUPER_PICKAXE_SIZE; + MAX_BRUSH_RADIUS = limit.MAX_BRUSH_RADIUS; + MAX_BUTCHER_RADIUS = limit.MAX_BUTCHER_RADIUS; } public FaweLimit copy() { @@ -279,13 +351,20 @@ public class FaweLimit { limit.MAX_FAILS = MAX_FAILS; limit.MAX_ITERATIONS = MAX_ITERATIONS; limit.MAX_HISTORY = MAX_HISTORY; + limit.SCHEM_FILE_SIZE_LIMIT = SCHEM_FILE_SIZE_LIMIT; + limit.SCHEM_FILE_NUM_LIMIT = SCHEM_FILE_NUM_LIMIT; limit.FAST_PLACEMENT = FAST_PLACEMENT; limit.CONFIRM_LARGE = CONFIRM_LARGE; limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS; limit.STRIP_NBT = STRIP_NBT; limit.UNIVERSAL_DISALLOWED_BLOCKS = UNIVERSAL_DISALLOWED_BLOCKS; + limit.ALLOW_LEGACY = ALLOW_LEGACY; limit.DISALLOWED_BLOCKS = DISALLOWED_BLOCKS; limit.REMAP_PROPERTIES = REMAP_PROPERTIES; + limit.MAX_RADIUS = MAX_RADIUS; + limit.MAX_SUPER_PICKAXE_SIZE = MAX_SUPER_PICKAXE_SIZE; + limit.MAX_BRUSH_RADIUS = MAX_BRUSH_RADIUS; + limit.MAX_BUTCHER_RADIUS = MAX_BUTCHER_RADIUS; return limit; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BlockVector3ChunkMap.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BlockVector3ChunkMap.java index a9f8a0210..919556847 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BlockVector3ChunkMap.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BlockVector3ChunkMap.java @@ -31,7 +31,7 @@ public class BlockVector3ChunkMap implements IAdaptedMap implements int cx = (int) MathMan.untripleWorldCoordX(triple); int cy = (int) MathMan.untripleWorldCoordY(triple); int cz = (int) MathMan.untripleWorldCoordZ(triple); - pos.mutX((cx << 11) + pos.getBlockX()); - pos.mutY((cy << 9) + pos.getBlockY()); - pos.mutZ((cz << 11) + pos.getBlockZ()); + pos.mutX((cx << 11) + pos.x()); + pos.mutY((cy << 9) + pos.y()); + pos.mutZ((cz << 11) + pos.z()); return pos.toImmutable(); } } @@ -78,10 +78,53 @@ public class BlockVectorSet extends AbstractCollection implements return localMap != null && localMap.contains(x & 2047, ((y + 128) & 511) - 128, z & 2047); } + @Override + public void setOffset(final int x, final int z) { + // Do nothing + } + + @Override + public void setOffset(final int x, final int y, final int z) { + // Do nothing + } + + @Override + public boolean containsRadius(final int x, final int y, final int z, final int radius) { + if (radius <= 0) { + return contains(x, y, z); + } + // Quick corners check + if (!contains(x - radius, y, z - radius)) { + return false; + } + if (!contains(x + radius, y, z + radius)) { + return false; + } + if (!contains(x - radius, y, z + radius)) { + return false; + } + if (!contains(x + radius, y, z - radius)) { + return false; + } + // Slow but if someone wants to think of an elegant way then feel free to add it + for (int xx = -radius; xx <= radius; xx++) { + int rx = x + xx; + for (int yy = -radius; yy <= radius; yy++) { + int ry = y + yy; + for (int zz = -radius; zz <= radius; zz++) { + if (contains(rx, ry, z + zz)) { + return true; + } + } + } + } + return false; + } + @Override public boolean contains(Object o) { if (o instanceof BlockVector3 v) { - return contains(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + return contains(v.x(), v.y(), v.z()); } return false; } @@ -123,9 +166,9 @@ public class BlockVectorSet extends AbstractCollection implements int cy = (int) MathMan.untripleWorldCoordY(triple); int cz = (int) MathMan.untripleWorldCoordZ(triple); return mutable.setComponents( - (cx << 11) + localPos.getBlockX(), - (cy << 9) + localPos.getBlockY(), - (cz << 11) + localPos.getBlockZ() + (cx << 11) + localPos.x(), + (cy << 9) + localPos.y(), + (cz << 11) + localPos.z() ); } }; @@ -133,7 +176,7 @@ public class BlockVectorSet extends AbstractCollection implements @Override public boolean add(BlockVector3 vector) { - return add(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + return add(vector.x(), vector.y(), vector.z()); } public boolean add(int x, int y, int z) { @@ -149,12 +192,13 @@ public class BlockVectorSet extends AbstractCollection implements } public boolean remove(int x, int y, int z) { - int pair = MathMan.pair((short) (x >> 11), (short) (z >> 11)); - LocalBlockVectorSet localMap = localSets.get(pair); + int indexedY = (y + 128) >> 9; + long triple = MathMan.tripleWorldCoord((x >> 11), indexedY, (z >> 11)); + LocalBlockVectorSet localMap = localSets.get(triple); if (localMap != null) { - if (localMap.remove(x & 2047, y, z & 2047)) { + if (localMap.remove(x & 2047, ((y + 128) & 511) - 128, z & 2047)) { if (localMap.isEmpty()) { - localSets.remove(pair); + localSets.remove(triple); } return true; } @@ -166,7 +210,7 @@ public class BlockVectorSet extends AbstractCollection implements @Override public boolean remove(Object o) { if (o instanceof BlockVector3 v) { - return remove(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + return remove(v.x(), v.y(), v.z()); } return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/DelegateBlockVector3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/DelegateBlockVector3.java index b75e157b2..b13aece41 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/DelegateBlockVector3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/DelegateBlockVector3.java @@ -95,13 +95,8 @@ public class DelegateBlockVector3 extends BlockVector3 { } @Override - public int getX() { - return parent.getX(); - } - - @Override - public int getBlockX() { - return parent.getBlockX(); + public int x() { + return parent.x(); } @Override @@ -110,13 +105,8 @@ public class DelegateBlockVector3 extends BlockVector3 { } @Override - public int getY() { - return parent.getY(); - } - - @Override - public int getBlockY() { - return parent.getBlockY(); + public int y() { + return parent.y(); } @Override @@ -125,13 +115,8 @@ public class DelegateBlockVector3 extends BlockVector3 { } @Override - public int getZ() { - return parent.getZ(); - } - - @Override - public int getBlockZ() { - return parent.getBlockZ(); + public int z() { + return parent.z(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java index f7f451e79..b5667ccef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java @@ -4,7 +4,9 @@ public record IntPair(int x, int z) { @Override public int hashCode() { - return (x << 16) | (z & 0xFFFF); + int i = 1664525 * x + 1013904223; + int j = 1664525 * (z ^ -559038737) + 1013904223; + return i ^ j; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/LocalBlockVectorSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/LocalBlockVectorSet.java index 8e6cdabe8..72287b0a1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/LocalBlockVectorSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/LocalBlockVectorSet.java @@ -90,7 +90,7 @@ public class LocalBlockVectorSet implements BlockVector3Set { @Override public boolean contains(Object o) { if (o instanceof BlockVector3 v) { - return contains(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + return contains(v.x(), v.y(), v.z()); } return false; } @@ -100,14 +100,7 @@ public class LocalBlockVectorSet implements BlockVector3Set { return new LocalBlockVectorSet(offsetX, offsetY, offsetZ, set.clone()); } - /** - * If a radius is contained by the set - * - * @param x x radius center - * @param y y radius center - * @param z z radius center - * @return if radius is contained by the set - */ + @Override public boolean containsRadius(int x, int y, int z, int radius) { if (radius <= 0) { return contains(x, y, z); @@ -130,9 +123,11 @@ public class LocalBlockVectorSet implements BlockVector3Set { return false; } for (int xx = -radius; xx <= radius; xx++) { + int rx = x + xx; for (int yy = -radius; yy <= radius; yy++) { + int ry = y + yy; for (int zz = -radius; zz <= radius; zz++) { - if (contains(x + xx, y + yy, z + zz)) { + if (contains(rx, ry, z + zz)) { return true; } } @@ -141,27 +136,13 @@ public class LocalBlockVectorSet implements BlockVector3Set { return false; } - /** - * Set the offset applied to values when storing and reading to keep the values within -1024 to 1023. Uses default y offset - * of 128 to allow -64 -> 320 world height use. - * - * @param x x offset - * @param z z offset - */ + @Override public void setOffset(int x, int z) { this.offsetX = x; this.offsetZ = z; } - /** - * Set the offset applied to values when storing and reading to keep the x and z values within -1024 to 1023. Y values - * require keeping withing -256 and 255. - * - * @param x x offset - * @param y y offset - * @param z z offset - * @since 2.2.0 - */ + @Override public void setOffset(int x, int y, int z) { this.offsetX = x; this.offsetY = y; @@ -321,14 +302,14 @@ public class LocalBlockVectorSet implements BlockVector3Set { */ @Override public boolean add(BlockVector3 vector) { - return add(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + return add(vector.x(), vector.y(), vector.z()); } private int getIndex(BlockVector3 vector) { return MathMan.tripleSearchCoords( - vector.getBlockX() - offsetX, - vector.getBlockY() - offsetY, - vector.getBlockZ() - offsetZ + vector.x() - offsetX, + vector.y() - offsetY, + vector.z() - offsetZ ); } @@ -361,7 +342,7 @@ public class LocalBlockVectorSet implements BlockVector3Set { public boolean remove(Object o) { if (o instanceof BlockVector3) { BlockVector3 v = (BlockVector3) o; - return remove(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + return remove(v.x(), v.y(), v.z()); } return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableBlockVector3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableBlockVector3.java index baa20163f..e4cfda85a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableBlockVector3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableBlockVector3.java @@ -21,11 +21,11 @@ public class MutableBlockVector3 extends BlockVector3 { } public MutableBlockVector3(BlockVector3 other) { - this(other.getX(), other.getY(), other.getZ()); + this(other.x(), other.y(), other.z()); } public MutableBlockVector3 setComponents(BlockVector3 other) { - return setComponents(other.getBlockX(), other.getBlockY(), other.getBlockZ()); + return setComponents(other.x(), other.y(), other.z()); } private int x; @@ -47,20 +47,36 @@ public class MutableBlockVector3 extends BlockVector3 { } @Override - public final int getX() { + public final int x() { return x; } @Override - public final int getY() { + public final int y() { return y; } @Override - public final int getZ() { + public final int z() { return z; } + @Override + public BlockVector3 getMinimum(BlockVector3 v2) { + this.x = Math.min(v2.x(), x); + this.y = Math.min(v2.y(), y); + this.z = Math.min(v2.z(), z); + return this; + } + + @Override + public BlockVector3 getMaximum(BlockVector3 v2) { + this.x = Math.max(v2.x(), x); + this.y = Math.max(v2.y(), y); + this.z = Math.max(v2.z(), z); + return this; + } + @Override public MutableBlockVector3 mutX(double x) { this.x = (int) x; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableVector3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableVector3.java index 22d85d38a..3c6ad1334 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableVector3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/MutableVector3.java @@ -23,7 +23,7 @@ public class MutableVector3 extends Vector3 { } public MutableVector3(Vector3 other) { - this(other.getX(), other.getY(), other.getZ()); + this(other.x(), other.y(), other.z()); } public static MutableVector3 get(int x, int y, int z) { @@ -36,9 +36,9 @@ public class MutableVector3 extends Vector3 { @Override public MutableVector3 setComponents(Vector3 other) { - this.x = other.getX(); - this.y = other.getY(); - this.z = other.getZ(); + this.x = other.x(); + this.y = other.y(); + this.z = other.z(); return this; } @@ -95,17 +95,17 @@ public class MutableVector3 extends Vector3 { } @Override - public double getX() { + public double x() { return x; } @Override - public double getY() { + public double y() { return y; } @Override - public double getZ() { + public double z() { return z; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/OffsetBlockVector3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/OffsetBlockVector3.java index 044a623de..5e0d0ebe0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/OffsetBlockVector3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/OffsetBlockVector3.java @@ -11,18 +11,18 @@ public class OffsetBlockVector3 extends DelegateBlockVector3 { } @Override - public int getX() { - return super.getX() + offset.getX(); + public int x() { + return super.x() + offset.x(); } @Override - public int getY() { - return super.getY() + offset.getY(); + public int y() { + return super.y() + offset.y(); } @Override - public int getZ() { - return super.getZ() + offset.getZ(); + public int z() { + return super.z() + offset.z(); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/Vector3Impl.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/Vector3Impl.java index c1092a881..33706aee5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/Vector3Impl.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/Vector3Impl.java @@ -15,21 +15,21 @@ public class Vector3Impl extends Vector3 { } public Vector3Impl(Vector3 other) { - this(other.getX(), other.getY(), other.getZ()); + this(other.x(), other.y(), other.z()); } @Override - public final double getX() { + public final double x() { return x; } @Override - public final double getY() { + public final double y() { return y; } @Override - public final double getZ() { + public final double z() { return z; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/HeightMap.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/HeightMap.java index f9b2ce914..eeafc8646 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/HeightMap.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/HeightMap.java @@ -10,7 +10,6 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; -import java.lang.reflect.InvocationTargetException; import java.util.concurrent.ThreadLocalRandom; public interface HeightMap { @@ -45,7 +44,7 @@ public interface HeightMap { boolean layers ) throws MaxChangedBlocksException { BlockVector3 top = session.getMaximumPoint(); - int maxY = top.getBlockY(); + int maxY = top.y(); Location min = new Location(session.getWorld(), pos.subtract(size, size, size).toVector3()); BlockVector3 max = pos.add(size, maxY, size); Region region = new CuboidRegion(session.getWorld(), min.toBlockPoint(), max); @@ -81,9 +80,9 @@ public interface HeightMap { int maxY = session.getMaxY(); int minY = session.getMinY(); int diameter = 2 * size + 1; - int centerX = pos.getBlockX(); - int centerZ = pos.getBlockZ(); - int centerY = pos.getBlockY(); + int centerX = pos.x(); + int centerZ = pos.z(); + int centerY = pos.y(); int[] oldData = new int[diameter * diameter]; int[] newData = new int[oldData.length]; if (layers) { // Pixel accuracy @@ -92,7 +91,7 @@ public interface HeightMap { } if (towards) { double sizePowInv = 1d / Math.pow(size, yscale); - int targetY = pos.getBlockY(); + int targetY = pos.y(); int tmpY = targetY; for (int x = -size; x <= size; x++) { int xx = centerX + x; @@ -133,7 +132,7 @@ public interface HeightMap { } } } else { - int height = pos.getBlockY(); + int height = pos.y(); for (int x = -size; x <= size; x++) { int xx = centerX + x; for (int z = -size; z <= size; z++) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/RotatableHeightMap.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/RotatableHeightMap.java index 291f8e754..a452a80f4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/RotatableHeightMap.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/RotatableHeightMap.java @@ -24,7 +24,7 @@ public class RotatableHeightMap extends AbstractDelegateHeightMap { mutable.mutX(x); mutable.mutZ(z); BlockVector3 pos = transform.apply(mutable.setComponents(x, 0, z)).toBlockPoint(); - return super.getHeight(pos.getBlockX(), pos.getBlockZ()); + return super.getHeight(pos.x(), pos.z()); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ScalableHeightMap.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ScalableHeightMap.java index c4481da46..bc845127d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ScalableHeightMap.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ScalableHeightMap.java @@ -56,22 +56,22 @@ public class ScalableHeightMap implements HeightMap { public static ScalableHeightMap fromClipboard(Clipboard clipboard, int minY, int maxY) { BlockVector3 dim = clipboard.getDimensions(); - char[][] heightArray = new char[dim.getBlockX()][dim.getBlockZ()]; - int clipMinX = clipboard.getMinimumPoint().getBlockX(); - int clipMinZ = clipboard.getMinimumPoint().getBlockZ(); - int clipMinY = clipboard.getMinimumPoint().getBlockY(); - int clipMaxY = clipboard.getMaximumPoint().getBlockY(); + char[][] heightArray = new char[dim.x()][dim.z()]; + int clipMinX = clipboard.getMinimumPoint().x(); + int clipMinZ = clipboard.getMinimumPoint().z(); + int clipMinY = clipboard.getMinimumPoint().y(); + int clipMaxY = clipboard.getMaximumPoint().y(); int clipHeight = clipMaxY - clipMinY + 1; HashSet visited = new HashSet<>(); MutableBlockVector3 bv = new MutableBlockVector3(); for (BlockVector3 pos : clipboard.getRegion()) { - IntPair pair = new IntPair(pos.getBlockX(), pos.getBlockZ()); + IntPair pair = new IntPair(pos.x(), pos.z()); if (visited.contains(pair)) { continue; } visited.add(pair); - int xx = pos.getBlockX(); - int zz = pos.getBlockZ(); + int xx = pos.x(); + int zz = pos.z(); int highestY = clipMinY; bv.setComponents(pos); for (int y = clipMinY; y <= clipMaxY; y++) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear2DRandom.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear2DRandom.java new file mode 100644 index 000000000..04a837b72 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear2DRandom.java @@ -0,0 +1,50 @@ +package com.fastasyncworldedit.core.math.random; + +import static com.fastasyncworldedit.core.math.random.Linear3DRandom.doubleDiv; +import static java.lang.Math.floorDiv; + +/** + * A {@link SimpleRandom} that deterministically maps coordinates + * to values. + * @since 2.9.2 + */ +public class Linear2DRandom implements SimpleRandom { + private final int xScale; + private final int zScale; + + /** + * Creates a new {@link Linear2DRandom} instance + * + * @param xScale the scale applied to the x component of a coordinate + * @param zScale the scale applied to the z component of a coordinate + */ + public Linear2DRandom(final int xScale, final int zScale) { + this.xScale = xScale; + this.zScale = zScale; + } + + @Override + public double nextDouble(final int x, final int y, final int z) { + return nextDouble(x, y, z, 1d); + } + + @Override + public double nextDouble(final int x, final int y, final int z, double bound) { + double index = (doubleDiv(x, this.xScale) + doubleDiv(z, this.zScale)) % bound; + if (index < 0) { + index += bound; + } + return index; + + } + + @Override + public int nextInt(final int x, final int y, final int z, final int bound) { + int index = (floorDiv(x, this.xScale) + floorDiv(z, this.zScale)) % bound; + if (index < 0) { + index += bound; + } + return index; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear3DRandom.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear3DRandom.java new file mode 100644 index 000000000..a1ab87045 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/Linear3DRandom.java @@ -0,0 +1,58 @@ +package com.fastasyncworldedit.core.math.random; + +import static java.lang.Math.floorDiv; + +/** + * A {@link SimpleRandom} that deterministically maps coordinates + * to values. + * @since 2.9.2 + */ +public class Linear3DRandom implements SimpleRandom { + + private final int xScale; + private final int yScale; + private final int zScale; + + /** + * Creates a new {@link Linear3DRandom} instance + * + * @param xScale the scale applied to the x component of a coordinate + * @param yScale the scale applied to the y component of a coordinate + * @param zScale the scale applied to the z component of a coordinate + */ + public Linear3DRandom(final int xScale, final int yScale, final int zScale) { + this.xScale = xScale; + this.yScale = yScale; + this.zScale = zScale; + } + + @Override + public double nextDouble(final int x, final int y, final int z) { + return nextDouble(x, y, z, 1d); + } + + @Override + public double nextDouble(final int x, final int y, final int z, double bound) { + double index = (doubleDiv(x, this.xScale) + doubleDiv(y, this.yScale) + doubleDiv(z, this.zScale)) % bound; + if (index < 0) { + index += bound; + } + return index; + } + + // used to avoid explicit conversion at call site + static double doubleDiv(double dividend, double divisor) { + // add a minimal value to avoid too many integral values hitting the exact weight of an entry in SimpleRandomCollection + return Math.nextUp(dividend) / divisor; + } + + @Override + public int nextInt(final int x, final int y, final int z, final int bound) { + int index = (floorDiv(x, this.xScale) + floorDiv(y, this.yScale) + floorDiv(z, this.zScale)) % bound; + if (index < 0) { + index += bound; + } + return index; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimpleRandom.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimpleRandom.java index e38214936..8b22b66a2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimpleRandom.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimpleRandom.java @@ -13,6 +13,20 @@ public interface SimpleRandom { */ double nextDouble(int x, int y, int z); + /** + * Generate a random double from three integer components. + * The generated value is between 0 (inclusive) and {@code bound} (exclusive). + * + * @param x the first component + * @param y the second component + * @param z the third component + * @param bound upper bound (exclusive) + * @return a double between 0 (inclusive) and {@code bound} (exclusive) + */ + default double nextDouble(int x, int y, int z, double bound) { + return nextDouble(x, y, z) * bound; + } + /** * Generate a random integer from three integer components. * The generated value is between 0 (inclusive) and 1 (exclusive) @@ -24,8 +38,8 @@ public interface SimpleRandom { * @return a random integer between 0 (inclusive) and {@code bound} (exclusive) */ default int nextInt(int x, int y, int z, int bound) { - double val = nextDouble(x, y, z); - return (int) (val * bound); + double val = nextDouble(x, y, z, bound); + return (int) val; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimplexNoiseGenerator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimplexNoiseGenerator.java index 8d8aeedf5..d690509dc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimplexNoiseGenerator.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/random/SimplexNoiseGenerator.java @@ -8,12 +8,12 @@ public class SimplexNoiseGenerator implements NoiseGenerator { @Override public float noise(Vector2 position) { - return convert(SimplexNoise.noise(position.getX(), position.getZ())); + return convert(SimplexNoise.noise(position.x(), position.z())); } @Override public float noise(Vector3 position) { - return convert(SimplexNoise.noise(position.getX(), position.getY(), position.getZ())); + return convert(SimplexNoise.noise(position.x(), position.y(), position.z())); } private float convert(double d) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java new file mode 100644 index 000000000..c41d8db1d --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java @@ -0,0 +1,7 @@ +package com.fastasyncworldedit.core.nbt; + +import org.enginehub.linbus.tree.LinCompoundTag; + +record EagerFaweCompoundTag(LinCompoundTag linTag) implements FaweCompoundTag { + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java new file mode 100644 index 000000000..52e38908d --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java @@ -0,0 +1,44 @@ +package com.fastasyncworldedit.core.nbt; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import org.enginehub.linbus.tree.LinCompoundTag; + +/** + * A wrapper around compound tags, potentially lazily transformed. + * @since 2.11.2 + */ +public sealed interface FaweCompoundTag permits EagerFaweCompoundTag, LazyFaweCompoundTag { + + /** + * {@return a lazy compound component backed by a lazy reference} + * @param lazyReference the lazy reference to the actual compound tag + */ + static FaweCompoundTag of(LazyReference lazyReference) { + return new LazyFaweCompoundTag(lazyReference::getValue); + } + + /** + * {@return a lazy compound component backed by a supplier} + * Invocations to the supplier are memoized. + * @param supplier the supplier for the actual compound tag + */ + static FaweCompoundTag of(Supplier supplier) { + return new LazyFaweCompoundTag(Suppliers.memoize(supplier)); + } + + /** + * {@return a direct reference tho the given compound tag} + * @param linCompoundTag the tag to wrap + */ + static FaweCompoundTag of(LinCompoundTag linCompoundTag) { + return new EagerFaweCompoundTag(linCompoundTag); + } + + /** + * {@return the underlying tag} + */ + LinCompoundTag linTag(); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java new file mode 100644 index 000000000..afd0e4e48 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java @@ -0,0 +1,14 @@ +package com.fastasyncworldedit.core.nbt; + +import org.enginehub.linbus.tree.LinCompoundTag; + +import java.util.function.Supplier; + +record LazyFaweCompoundTag(Supplier linTagSupplier) implements FaweCompoundTag { + + @Override + public LinCompoundTag linTag() { + return this.linTagSupplier().get(); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java index 19fa1293a..f308d4806 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java @@ -2,8 +2,8 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.sk89q.worldedit.regions.Region; -import org.jetbrains.annotations.Range; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -11,30 +11,29 @@ import javax.annotation.Nullable; */ public interface Filter { - /** - * Checks whether a chunk should be read. - * - * @param chunkX the x coordinate in the chunk - * @param chunkZ the z coordinate in the chunk - */ - default boolean appliesChunk( - @Range(from = 0, to = 15) int chunkX, - @Range(from = 0, to = 15) int chunkZ - ) { - return true; - } +// /** +// * Checks whether a chunk should be read. +// * +// * @param chunkX the x coordinate in the chunk +// * @param chunkZ the z coordinate in the chunk +// */ +// default boolean appliesChunk( +// int chunkX, +// int chunkZ +// ) { +// return true; +// } /** - * Do something with the IChunk
- Return null if you don't want to filter blocks
- - * Return the chunk if you do want to filter blocks
+ * Do something with the IChunk
*/ - default T applyChunk(T chunk, @Nullable Region region) { + default @Nonnull T applyChunk(T chunk, @Nullable Region region) { return chunk; } - default boolean appliesLayer(IChunk chunk, int layer) { - return true; - } +// default boolean appliesLayer(IChunk chunk, int layer) { +// return true; +// } /** * Make changes to the block here
- e.g., block.setId(...)
- Note: Performance is diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index 5eeafe28e..7bce208fc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -3,15 +3,16 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Map; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.function.Function; @@ -50,7 +51,7 @@ public interface IBatchProcessor { } /** - * Convert this processor into an Extent based processor instead of a queue batch based on. + * Convert this processor into an Extent based processor instead of a queue batch based one. */ @Nullable Extent construct(Extent child); @@ -58,48 +59,45 @@ public interface IBatchProcessor { /** * Utility method to trim a chunk based on min and max Y (inclusive). * - * @param keepInsideRange if all blocks inside the range (inclusive) should be kept (default) + * @param keepInsideRange if all blocks inside the range (inclusive) should be kept (default), or removed * @return false if chunk is empty of blocks */ default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsideRange) { - int minLayer = (minY - 1) >> 4; - int maxLayer = (maxY + 1) >> 4; + int minLayer = minY >> 4; + int maxLayer = maxY >> 4; if (keepInsideRange) { - for (int layer = set.getMinSectionPosition(); layer <= minLayer; layer++) { - if (set.hasSection(layer)) { - if (layer == minLayer) { - char[] arr = set.loadIfPresent(layer); - if (arr != null) { - int index = (minY & 15) << 8; - for (int i = 0; i < index; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - } else { - arr = new char[4096]; - } - set.setBlocks(layer, arr); - } else { - set.setBlocks(layer, null); + for (int layer = set.getMinSectionPosition(); layer <= set.getMaxSectionPosition(); layer++) { + if (!set.hasSection(layer)) { + continue; + } + // wipe all data from chunk layers above or below the max / min layer + if (layer < minLayer || layer > maxLayer) { + set.setBlocks(layer, null); + continue; + } + // if chunk layer / section is fully enclosed by minY to maxY, keep as is + if (layer > minLayer && layer < maxLayer) { + continue; + } + char[] blocks = set.loadIfPresent(layer); + if (blocks == null) { + continue; + } + // When on the minimum layer (as defined by minY), remove blocks up to minY (exclusive) + if (layer == minLayer) { + int index = (minY & 15) << 8; + for (int i = 0; i < index; i++) { + blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; } } - } - for (int layer = maxLayer; layer < set.getMaxSectionPosition(); layer++) { - if (set.hasSection(layer)) { - if (layer == maxLayer) { - char[] arr = set.loadIfPresent(layer); - if (arr != null) { - int index = ((maxY + 1) & 15) << 8; - for (int i = index; i < arr.length; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - } else { - arr = new char[4096]; - } - set.setBlocks(layer, arr); - } else { - set.setBlocks(layer, null); + // When on the maximum layer (as defined by maxY), remove blocks above maxY (exclusive) + if (layer == maxLayer) { + int index = ((maxY & 15) + 1) << 8; + for (int i = index; i < blocks.length; i++) { + blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; } } + set.setBlocks(layer, blocks); } try { int layer = (minY - 15) >> 4; @@ -155,13 +153,15 @@ public interface IBatchProcessor { * Utility method to trim entity and blocks with a provided contains function. * * @return false if chunk is empty of NBT + * @deprecated tiles are stored in chunk-normalised coordinate space and thus cannot use the same function as entities */ + @Deprecated(forRemoval = true, since = "2.8.4") default boolean trimNBT(IChunkSet set, Function contains) { - Set ents = set.getEntities(); + Collection ents = set.entities(); if (!ents.isEmpty()) { - ents.removeIf(ent -> !contains.apply(ent.getEntityPosition().toBlockPoint())); + ents.removeIf(ent -> !contains.apply(NbtUtils.entityPosition(ent).toBlockPoint())); } - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (!tiles.isEmpty()) { tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !contains .apply(blockVector3CompoundTagEntry.getKey())); @@ -169,6 +169,26 @@ public interface IBatchProcessor { return !tiles.isEmpty() || !ents.isEmpty(); } + /** + * Utility method to trim entity and blocks with a provided contains function. + * + * @return false if chunk is empty of NBT + * @since 2.8.4 + */ + default boolean trimNBT( + IChunkSet set, Function containsEntity, Function containsTile + ) { + Collection ents = set.entities(); + if (!ents.isEmpty()) { + ents.removeIf(ent -> !containsEntity.apply(NbtUtils.entityPosition(ent).toBlockPoint())); + } + Map tiles = set.tiles(); + if (!tiles.isEmpty()) { + tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey())); + } + return !tiles.isEmpty() || !ents.isEmpty(); + } + /** * Join two processors and return the result. */ diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java index ff6842c0a..3a9d71da1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java @@ -3,6 +3,8 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; @@ -12,10 +14,13 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.registry.BlockRegistry; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; +import java.util.Collection; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.IntStream; /** @@ -54,11 +59,38 @@ public interface IBlocks extends Trimable { BlockState getBlock(int x, int y, int z); - Map getTiles(); + @Deprecated(forRemoval = true, since = "2.11.2") + default Map getTiles() { + return AdaptedMap.values(tiles(), ct -> FaweCompoundTag.of(ct.toLinTag()), IBlocks::toCompoundTag); + } - CompoundTag getTile(int x, int y, int z); + Map tiles(); - Set getEntities(); + @Deprecated(forRemoval = true, since = "2.11.2") + default CompoundTag getTile(int x, int y, int z) { + final FaweCompoundTag tile = tile(x, y, z); + if (tile == null) { + return null; + } + return toCompoundTag(tile); + } + + @SuppressWarnings({"deprecation"}) + private static @Nonnull CompoundTag toCompoundTag(FaweCompoundTag tile) { + return new CompoundTag(tile.linTag()); + } + + @Nullable + FaweCompoundTag tile(int x, int y, int z); + + @Deprecated(forRemoval = true, since = "2.11.2") + default Set getEntities() { + return entities().stream() + .map(IBlocks::toCompoundTag) + .collect(Collectors.toSet()); + } + + Collection entities(); BiomeType getBiomeType(int x, int y, int z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunk.java index 126a5cd13..2586ea24c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunk.java @@ -1,8 +1,8 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import org.jetbrains.annotations.Range; import javax.annotation.Nullable; @@ -25,7 +25,6 @@ public interface IChunk extends Trimable, IChunkGet, IChunkSet { * * @return the x coordinate of the chunk */ - @Range(from = 0, to = 15) int getX(); /** @@ -33,9 +32,18 @@ public interface IChunk extends Trimable, IChunkGet, IChunkSet { * * @return the z coordinate of the chunk */ - @Range(from = 0, to = 15) int getZ(); + /** + * Return the minimum block coordinate of the chunk + * + * @return BlockVector3 of minimum block coordinate + * @since 2.8.4 + */ + default BlockVector3 getChunkBlockCoord() { + return BlockVector3.at(getX() << 4, getMinY(), getZ() << 4); + } + /** * If the chunk is a delegate, returns its parent's root * diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkCache.java index ce2761390..8a704e9cb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkCache.java @@ -1,14 +1,12 @@ package com.fastasyncworldedit.core.queue; -import org.jetbrains.annotations.Range; - /** * IGetBlocks may be cached by the WorldChunkCache so that it can be used between multiple * IQueueExtents - avoids conversion between a palette and raw data on every block get */ public interface IChunkCache extends Trimable { - T get(@Range(from = 0, to = 15) int chunkX, @Range(from = 0, to = 15) int chunkZ); + T get(int chunkX, int chunkZ); @Override default boolean trim(boolean aggressive) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java index ec6162798..615f5fb50 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java @@ -1,11 +1,7 @@ package com.fastasyncworldedit.core.queue; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -16,6 +12,12 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import java.util.ArrayList; import java.util.HashMap; @@ -39,9 +41,9 @@ public interface IChunkExtent extends Extent { } @Override - default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + default boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4); - return chunk.setTile(x & 15, y, z & 15, tile); + return chunk.tile(x & 15, y, z & 15, tile); } @Override @@ -52,8 +54,8 @@ public interface IChunkExtent extends Extent { @Override default boolean setBiome(BlockVector3 position, BiomeType biome) { - final IChunk chunk = getOrCreateChunk(position.getX() >> 4, position.getZ() >> 4); - return chunk.setBiome(position.getX() & 15, position.getY(), position.getZ() & 15, biome); + final IChunk chunk = getOrCreateChunk(position.x() >> 4, position.z() >> 4); + return chunk.setBiome(position.x() & 15, position.y(), position.z() & 15, biome); } @Override @@ -76,8 +78,8 @@ public interface IChunkExtent extends Extent { @Override default BiomeType getBiome(BlockVector3 position) { - final IChunk chunk = getOrCreateChunk(position.getX() >> 4, position.getZ() >> 4); - return chunk.getBiomeType(position.getX() & 15, position.getY(), position.getZ() & 15); + final IChunk chunk = getOrCreateChunk(position.x() >> 4, position.z() >> 4); + return chunk.getBiomeType(position.x() & 15, position.y(), position.z() & 15); } @Override @@ -124,19 +126,19 @@ public interface IChunkExtent extends Extent { @Override default Entity createEntity(Location location, BaseEntity entity, UUID uuid) { final IChunk chunk = getOrCreateChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4); - Map map = new HashMap<>(entity.getNbtData().getValue()); //do not modify original entity data - map.put("Id", new StringTag(entity.getType().getName())); + Map> map = new HashMap<>(entity.getNbt().value()); //do not modify original entity data + map.put("Id", LinStringTag.of(entity.getType().getName())); //Set pos - List posList = new ArrayList<>(); - posList.add(new DoubleTag(location.getX())); - posList.add(new DoubleTag(location.getY())); - posList.add(new DoubleTag(location.getZ())); - map.put("Pos", new ListTag(DoubleTag.class, posList)); + List posList = new ArrayList<>(); + posList.add(LinDoubleTag.of(location.x())); + posList.add(LinDoubleTag.of(location.y())); + posList.add(LinDoubleTag.of(location.z())); + map.put("Pos", LinListTag.of(LinTagType.doubleTag(), posList)); - NBTUtils.addUUIDToMap(map, uuid); + NbtUtils.addUUIDToMap(map, uuid); - chunk.setEntity(new CompoundTag(map)); + chunk.entity(FaweCompoundTag.of(LinCompoundTag.of(map))); return new IChunkEntity(this, location, uuid, entity); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java index 8004f7098..b72690029 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.InputExtent; import com.sk89q.worldedit.math.BlockVector3; @@ -25,7 +26,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { @Override default BiomeType getBiome(BlockVector3 position) { - return getBiomeType(position.getX(), position.getY(), position.getZ()); + return getBiomeType(position.x(), position.y(), position.z()); } @Override @@ -46,17 +47,54 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { > T call(IChunkSet set, Runnable finalize); - CompoundTag getEntity(UUID uuid); + @Deprecated(forRemoval = true, since = "2.11.2") + default CompoundTag getEntity(UUID uuid) { + final FaweCompoundTag entity = entity(uuid); + if (entity == null) { + return null; + } + return new CompoundTag(entity.linTag()); + } + + /** + * {@return the compound tag describing the entity with the given UUID, if any} + * @param uuid the uuid of the entity + */ + @Nullable FaweCompoundTag entity(UUID uuid); + + @Override + @Deprecated(forRemoval = true, since = "2.11.2") + default CompoundTag getTile(int x, int y, int z) { + return IBlocks.super.getTile(x, y, z); + } boolean isCreateCopy(); - void setCreateCopy(boolean createCopy); + /** + * Not for external API use. Internal use only. + */ + int setCreateCopy(boolean createCopy); @Nullable - default IChunkGet getCopy() { + default IChunkGet getCopy(int key) { return null; } + /** + * Lock the {@link IChunkGet#call(IChunkSet, Runnable)} method to the current thread using a reentrant lock. Also locks + * related methods e.g. {@link IChunkGet#setCreateCopy(boolean)} + * + * @since 2.8.2 + */ + default void lockCall() {} + + /** + * Unlock {@link IChunkGet#call(IChunkSet, Runnable)} (and other related methods) to executions from other threads + * + * @since 2.8.2 + */ + default void unlockCall() {} + /** * Flush the block lighting array (section*blocks) to the chunk GET between the given section indices. Negative allowed. * diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java index 1af60b3a2..fc1482d6e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java @@ -1,7 +1,9 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector3; @@ -25,7 +27,7 @@ public interface IChunkSet extends IBlocks, OutputExtent { @Override default boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override @@ -36,7 +38,12 @@ public interface IChunkSet extends IBlocks, OutputExtent { boolean isEmpty(); @Override - boolean setTile(int x, int y, int z, CompoundTag tile); + @Deprecated(forRemoval = true, since = "2.11.2") + default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); + } + + boolean tile(int x, int y, int z, FaweCompoundTag tag); @Override void setBlockLight(int x, int y, int z, int value); @@ -53,7 +60,12 @@ public interface IChunkSet extends IBlocks, OutputExtent { void setFullBright(int layer); - void setEntity(CompoundTag tag); + @Deprecated(forRemoval = true, since = "2.11.2") + default void setEntity(CompoundTag tag) { + entity(FaweCompoundTag.of(tag::toLinTag)); + } + + void entity(FaweCompoundTag tag); void removeEntity(UUID uuid); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java index a4bb54017..1e172dd19 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java @@ -9,21 +9,11 @@ public interface IDelegateFilter extends Filter { Filter getParent(); - @Override - default boolean appliesChunk(int chunkX, int chunkZ) { - return getParent().appliesChunk(chunkX, chunkZ); - } - @Override default V applyChunk(V chunk, @Nullable Region region) { return getParent().applyChunk(chunk, region); } - @Override - default boolean appliesLayer(IChunk chunk, int layer) { - return getParent().appliesLayer(chunk, layer); - } - @Override default void applyBlock(FilterBlock block) { getParent().applyBlock(block); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java index 72732378d..9dda1d006 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java @@ -36,4 +36,18 @@ public interface IQueueChunk> extends IChunk, Callable { } } + /** + * Get if the thank has any running tasks, locked locks, etc. + */ + default boolean hasRunning() { + return false; + } + + /** + * Prevent set operations to the chunk, should typically be used when a chunk is submitted before the edit is necessarily + * completed. + */ + default void lockSet() { + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java index a5a29f170..d09b7f04b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java @@ -2,12 +2,14 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.IBatchProcessorHolder; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedCharFilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import org.jetbrains.annotations.Range; import javax.annotation.Nullable; import java.io.Flushable; @@ -51,12 +53,12 @@ public interface IQueueExtent extends Flushable, Trimable, ICh * Get the cached get object. This is faster than getting the object using NMS and allows for * wrapping. */ - IChunkGet getCachedGet(@Range(from = 0, to = 15) int chunkX, @Range(from = 0, to = 15) int chunkZ); + IChunkGet getCachedGet(int chunkX, int chunkZ); /** * Get the cached chunk set object. */ - IChunkSet getCachedSet(@Range(from = 0, to = 15) int chunkX, @Range(from = 0, to = 15) int chunkZ); + IChunkSet getCachedSet(int chunkX, int chunkZ); /** * Submit the chunk so that it's changes are applied to the world @@ -116,7 +118,7 @@ public interface IQueueExtent extends Flushable, Trimable, ICh * A filter block is used to iterate over blocks / positions. Essentially combines BlockVector3, * Extent and BlockState functions in a way that avoids lookups. */ - ChunkFilterBlock initFilterBlock(); + ChunkFilterBlock createFilterBlock(); /** * Returns the number of chunks in this queue. @@ -130,21 +132,30 @@ public interface IQueueExtent extends Flushable, Trimable, ICh */ boolean isEmpty(); - default ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, Region region, int chunkX, int chunkZ, boolean full) { - if (!filter.appliesChunk(chunkX, chunkZ)) { - return block; - } + default ChunkFilterBlock apply( + @Nullable ChunkFilterBlock block, + Filter filter, + Region region, + int chunkX, + int chunkZ, + boolean full + ) { +// if (!filter.appliesChunk(chunkX, chunkZ)) { +// return block; +// } T chunk = this.getOrCreateChunk(chunkX, chunkZ); - // Initialize - chunk.init(this, chunkX, chunkZ); - chunk.setFastMode(isFastMode()); T newChunk = filter.applyChunk(chunk, region); if (newChunk != null) { chunk = newChunk; if (block == null) { - block = this.initFilterBlock(); + if (SimdSupport.useVectorApi() && filter instanceof VectorizedFilter) { + block = new VectorizedCharFilterBlock(this); + } else { + block = this.createFilterBlock(); + } } + block.initChunk(chunkX, chunkZ); chunk.filterBlocks(filter, block, region, full); } this.submit(chunk); @@ -156,7 +167,7 @@ public interface IQueueExtent extends Flushable, Trimable, ICh final Set chunks = region.getChunks(); ChunkFilterBlock block = null; for (BlockVector2 chunk : chunks) { - block = apply(block, filter, region, chunk.getX(), chunk.getZ(), full); + block = apply(block, filter, region, chunk.x(), chunk.z(), full); } flush(); return filter; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java index 5d0641c81..4a88118ef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.queue; import com.sk89q.jnbt.CompoundTag; +@Deprecated(forRemoval = true, since = "2.11.2") public interface ITileInput { CompoundTag getTile(int x, int y, int z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index 2d2b45aae..56a238166 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -14,10 +14,13 @@ import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder; import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; @@ -45,6 +48,7 @@ import java.util.stream.IntStream; public class ParallelQueueExtent extends PassthroughExtent { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static final ThreadLocal extents = new ThreadLocal<>(); private final World world; private final QueueHandler handler; @@ -73,10 +77,36 @@ public class ParallelQueueExtent extends PassthroughExtent { this.fastmode = fastmode; } + /** + * Removes the extent currently associated with the calling thread. + */ + public static void clearCurrentExtent() { + extents.remove(); + } + + /** + * Sets the extent associated with the calling thread. + */ + public static void setCurrentExtent(Extent extent) { + extents.set(extent); + } + + private void enter(Extent extent) { + setCurrentExtent(extent); + } + + private void exit() { + clearCurrentExtent(); + } + @Override @SuppressWarnings({"unchecked", "rawtypes"}) public IQueueExtent getExtent() { - return (IQueueExtent) super.getExtent(); + Extent extent = extents.get(); + if (extent == null) { + extent = super.getExtent(); + } + return (IQueueExtent) extent; } @Override @@ -103,17 +133,23 @@ public class ParallelQueueExtent extends PassthroughExtent { // Get a pool, to operate on the chunks in parallel final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS); - if (size <= 1 && chunksIter.hasNext()) { - BlockVector2 pos = chunksIter.next(); - getExtent().apply(null, filter, region, pos.getX(), pos.getZ(), full); + if (size <= 1) { + // if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially + ChunkFilterBlock block = null; + while (chunksIter.hasNext()) { + BlockVector2 pos = chunksIter.next(); + block = getExtent().apply(block, filter, region, pos.x(), pos.z(), full); + } } else { final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> { try { final Filter newFilter = filter.fork(); + final Region newRegion = region.clone(); // Create a chunk that we will reuse/reset for each operation final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue(); queue.setFastMode(fastmode); queue.setFaweExceptionArray(faweExceptionReasonsUsed); + enter(queue); synchronized (queue) { try { ChunkFilterBlock block = null; @@ -127,10 +163,10 @@ public class ParallelQueueExtent extends PassthroughExtent { break; } final BlockVector2 pos = chunksIter.next(); - chunkX = pos.getX(); - chunkZ = pos.getZ(); + chunkX = pos.x(); + chunkZ = pos.z(); } - block = queue.apply(block, newFilter, region, chunkX, chunkZ, full); + block = queue.apply(block, newFilter, newRegion, chunkX, chunkZ, full); } queue.flush(); } catch (Throwable t) { @@ -154,6 +190,8 @@ public class ParallelQueueExtent extends PassthroughExtent { exceptionCount++; LOGGER.warn(message); } + } finally { + exit(); } })).toArray(ForkJoinTask[]::new); // Join filters @@ -186,7 +224,9 @@ public class ParallelQueueExtent extends PassthroughExtent { @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { - return this.changes = apply(region, new LinkedFilter<>(pattern, new CountFilter()), true).getChild().getTotal(); + VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern); + var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter()); + return this.changes = apply(region, filter, true).getRight().getTotal(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java index 014b94fce..7bdbf4645 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java @@ -68,7 +68,8 @@ public abstract class QueueHandler implements Trimable, Runnable { * Main "work-horse" queue for FAWE. Handles chunk submission (and chunk submission alone). Blocking in order to forcibly * prevent overworking/over-submission of chunk process tasks. */ - private final ThreadPoolExecutor blockingExecutor = FaweCache.INSTANCE.newBlockingExecutor(); + private final ThreadPoolExecutor blockingExecutor = FaweCache.INSTANCE.newBlockingExecutor( + "FAWE QueueHandler Blocking Executor - %d"); /** * Queue for tasks to be completed on the main thread. These take priority of tasks submitted to syncWhenFree queue */ @@ -407,7 +408,7 @@ public abstract class QueueHandler implements Trimable, Runnable { * Sets the current thread's {@link IQueueExtent} instance in the queue pool to null. */ public void unCache() { - queuePool.set(null); + queuePool.remove(); } private IQueueExtent pool() { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java index 198782ee3..b0239a5a3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java @@ -9,7 +9,6 @@ import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.internal.exception.FaweException; -import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; @@ -48,11 +47,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private static final Logger LOGGER = LogManagerCompat.getLogger(); - // Pool discarded chunks for reuse (can safely be cleared by another thread) - // private static final ConcurrentLinkedQueue CHUNK_POOL = new ConcurrentLinkedQueue<>(); // Chunks currently being queued / worked on - private final Long2ObjectLinkedOpenHashMap chunks = new Long2ObjectLinkedOpenHashMap<>(); - private final ConcurrentLinkedQueue submissions = new ConcurrentLinkedQueue<>(); + private final Long2ObjectLinkedOpenHashMap> chunks = new Long2ObjectLinkedOpenHashMap<>(); + private final ConcurrentLinkedQueue> submissions = new ConcurrentLinkedQueue<>(); private final ReentrantLock getChunkLock = new ReentrantLock(); private World world = null; private int minY = 0; @@ -62,8 +59,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private boolean initialized; private Thread currentThread; // Last access pointers - private IQueueChunk lastChunk; - private long lastPair = Long.MAX_VALUE; + private volatile IQueueChunk lastChunk; + private volatile long lastPair = Long.MAX_VALUE; private boolean enabledQueue = true; private boolean fastmode = false; // Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is @@ -142,12 +139,10 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen if (!this.initialized) { return; } - if (!this.chunks.isEmpty()) { - getChunkLock.lock(); - for (IChunk chunk : this.chunks.values()) { - chunk.recycle(); - } + getChunkLock.lock(); + try { this.chunks.clear(); + } finally { getChunkLock.unlock(); } this.enabledQueue = true; @@ -158,6 +153,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen this.setProcessor(EmptyBatchProcessor.getInstance()); this.setPostProcessor(EmptyBatchProcessor.getInstance()); this.world = null; + this.faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; } /** @@ -233,7 +229,6 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen } } if (chunk.isEmpty()) { - chunk.recycle(); Future result = Futures.immediateFuture(null); return (V) result; } @@ -283,6 +278,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private ChunkHolder poolOrCreate(int chunkX, int chunkZ) { ChunkHolder next = create(false); next.init(this, chunkX, chunkZ); + next.setFastMode(isFastMode()); return next; } @@ -360,7 +356,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen break; } loadCount++; - addChunkLoad(from.getBlockX(), from.getBlockZ()); + addChunkLoad(from.x(), from.z()); } } } @@ -454,7 +450,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen if (!chunks.isEmpty()) { getChunkLock.lock(); if (MemUtil.isMemoryLimited()) { - for (IQueueChunk chunk : chunks.values()) { + while (!chunks.isEmpty()) { + IQueueChunk chunk = chunks.removeFirst(); final Future future = submitUnchecked(chunk); if (future != null && !future.isDone()) { pollSubmissions(Settings.settings().QUEUE.PARALLEL_THREADS, true); @@ -462,21 +459,21 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen } } } else { - for (IQueueChunk chunk : chunks.values()) { + while (!chunks.isEmpty()) { + IQueueChunk chunk = chunks.removeFirst(); final Future future = submitUnchecked(chunk); if (future != null && !future.isDone()) { submissions.add(future); } } } - chunks.clear(); getChunkLock.unlock(); } pollSubmissions(0, true); } @Override - public ChunkFilterBlock initFilterBlock() { + public ChunkFilterBlock createFilterBlock() { return new CharFilterBlock(this); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java index ae976777c..76f2191ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java @@ -2,9 +2,9 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.util.collection.MemBlockSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; @@ -13,6 +13,7 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -74,7 +75,7 @@ public class BitSetBlocks implements IChunkSet { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { return false; } @@ -107,7 +108,7 @@ public class BitSetBlocks implements IChunkSet { } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { } @Override @@ -181,18 +182,18 @@ public class BitSetBlocks implements IChunkSet { } @Override - public Map getTiles() { + public Map tiles() { return Collections.emptyMap(); } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return null; } @Override - public Set getEntities() { - return Collections.emptySet(); + public Collection entities() { + return Collections.emptyList(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java index 85cadd9ef..c338033f0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java @@ -17,13 +17,25 @@ public abstract class CharBlocks implements IBlocks { protected static final Section FULL = new Section() { @Override public char[] get(CharBlocks blocks, int layer) { - return blocks.blocks[layer]; + char[] arr = blocks.blocks[layer]; + if (arr == null) { + // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues + return EMPTY.get(blocks, layer, false); + } + return arr; } // Ignore aggressive switch here. @Override public char[] get(CharBlocks blocks, int layer, boolean aggressive) { - return blocks.blocks[layer]; + char[] arr = blocks.blocks[layer]; + if (arr == null) { + // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues + synchronized (blocks.sectionLocks[layer]) { + return getSkipFull(blocks, layer, aggressive); + } + } + return arr; } @Override @@ -44,22 +56,7 @@ public abstract class CharBlocks implements IBlocks { if (blocks.sections[layer] == FULL) { return FULL.get(blocks, layer); } - char[] arr = blocks.blocks[layer]; - if (arr == null) { - arr = blocks.blocks[layer] = blocks.update(layer, null, aggressive); - if (arr == null) { - throw new IllegalStateException("Array cannot be null: " + blocks.getClass()); - } - } else { - blocks.blocks[layer] = blocks.update(layer, arr, aggressive); - if (blocks.blocks[layer] == null) { - throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass()); - } - } - if (blocks.blocks[layer] != null) { - blocks.sections[layer] = FULL; - } - return arr; + return getSkipFull(blocks, layer, aggressive); } } @@ -121,6 +118,7 @@ public abstract class CharBlocks implements IBlocks { public synchronized IChunkSet reset() { for (int i = 0; i < sectionCount; i++) { sections[i] = EMPTY; + blocks[i] = null; } return null; } @@ -251,6 +249,25 @@ public abstract class CharBlocks implements IBlocks { get(blocks, layer)[index] = value; } + static char[] getSkipFull(CharBlocks blocks, int layer, boolean aggressive) { + char[] arr = blocks.blocks[layer]; + if (arr == null) { + arr = blocks.blocks[layer] = blocks.update(layer, null, aggressive); + if (arr == null) { + throw new IllegalStateException("Array cannot be null: " + blocks.getClass()); + } + } else { + blocks.blocks[layer] = blocks.update(layer, arr, aggressive); + if (blocks.blocks[layer] == null) { + throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass()); + } + } + if (blocks.blocks[layer] != null) { + blocks.sections[layer] = FULL; + } + return arr; + } + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java index 2c89a7108..cd1c1b76f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.sk89q.worldedit.world.block.BaseBlock; @@ -20,7 +21,7 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java index 9ab8734ea..8d7c059ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java @@ -4,16 +4,18 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.Pool; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypesCache; +import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashSet; @@ -36,8 +38,8 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { public BiomeType[][] biomes; public char[][] light; public char[][] skyLight; - public BlockVector3ChunkMap tiles; - public HashSet entities; + public BlockVector3ChunkMap tiles; + public HashSet entities; public HashSet entityRemoves; public EnumMap heightMaps; private boolean fastMode = false; @@ -71,17 +73,17 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { } @Override - public Map getTiles() { + public Map tiles() { return tiles == null ? Collections.emptyMap() : tiles; } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return tiles == null ? null : tiles.get(x, y, z); } @Override - public Set getEntities() { + public Collection entities() { return entities == null ? Collections.emptySet() : entities; } @@ -128,16 +130,16 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { @Override public > boolean setBlock(BlockVector3 position, T block) throws WorldEditException { - return setBlock(position.getX(), position.getY(), position.getZ(), block); + return setBlock(position.x(), position.y(), position.z(), block); } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { if (tiles == null) { tiles = new BlockVector3ChunkMap<>(); } updateSectionIndexRange(y >> 4); - tiles.put(x, y, z, tile); + tiles.put(x, y, z, tag); return true; } @@ -255,11 +257,11 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { if (entities == null) { entities = new HashSet<>(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java index 8f7b8007c..273f44952 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java @@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -15,9 +15,9 @@ import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; @@ -48,28 +48,24 @@ public final class NullChunkGet implements IChunkGet { return BlockTypes.AIR.getDefaultState(); } - @Nonnull - public Map getTiles() { + @Override + public Map tiles() { return Collections.emptyMap(); } - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return null; - } - - @Nullable - public Set getEntities() { - return null; - } - - @Nullable - public CompoundTag getEntity(@Nonnull UUID uuid) { + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return null; } @Override - public void setCreateCopy(boolean createCopy) { + public Collection entities() { + return Collections.emptyList(); + } + + @Override + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -122,6 +118,11 @@ public final class NullChunkGet implements IChunkGet { return null; } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return null; + } + @Nonnull public char[] load(int layer) { return FaweCache.INSTANCE.EMPTY_CHAR_4096; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java index ca0dd3442..c21e932a9 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java @@ -4,9 +4,9 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +17,7 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; @@ -44,8 +45,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { private BiomeType[][] biomes; private char[][] light; private char[][] skyLight; - private BlockVector3ChunkMap tiles; - private HashSet entities; + private BlockVector3ChunkMap tiles; + private HashSet entities; private HashSet entityRemoves; private Map heightMaps; private boolean fastMode; @@ -64,8 +65,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { int sectionCount, char[][] light, char[][] skyLight, - BlockVector3ChunkMap tiles, - HashSet entities, + BlockVector3ChunkMap tiles, + HashSet entities, HashSet entityRemoves, Map heightMaps, char defaultOrdinal, @@ -116,18 +117,18 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public Map getTiles() { + public Map tiles() { return tiles == null ? Collections.emptyMap() : tiles; } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return tiles == null ? null : tiles.get(x, y, z); } @Override - public Set getEntities() { - return entities == null ? Collections.emptySet() : entities; + public Collection entities() { + return entities == null ? Collections.emptyList() : entities; } @Override @@ -218,11 +219,11 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - return setBiome(position.getX(), position.getY(), position.getZ(), biome); + return setBiome(position.x(), position.y(), position.z(), biome); } public void set(int x, int y, int z, char value) { - final int layer = y >> 4; + final int layer = (y >> 4) - minSectionPosition; final int index = (y & 15) << 8 | z << 4 | x; try { blocks[layer][index] = value; @@ -268,12 +269,12 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { updateSectionIndexRange(y >> 4); if (tiles == null) { tiles = new BlockVector3ChunkMap<>(); } - tiles.put(x, y, z, tile); + tiles.put(x, y, z, tag); return true; } @@ -358,7 +359,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { if (entities == null) { entities = new HashSet<>(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java index ec556d845..5e951cd2b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java @@ -1,51 +1,45 @@ package com.fastasyncworldedit.core.queue.implementation.chunk; -import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.queue.Pool; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent; +import com.fastasyncworldedit.core.util.MemUtil; +import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.atomic.AtomicBoolean; /** * An abstract {@link IChunk} class that implements basic get/set blocks. */ @SuppressWarnings("rawtypes") public class ChunkHolder> implements IQueueChunk { - - private static final Pool POOL = FaweCache.INSTANCE.registerPool( - ChunkHolder.class, - ChunkHolder::new, - Settings.settings().QUEUE.POOL - ); + private static final Logger LOGGER = LogManagerCompat.getLogger(); public static ChunkHolder newInstance() { - return POOL.poll(); + return new ChunkHolder(); } - private final Lock calledLock = new ReentrantLock(); - private volatile IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes) private volatile IChunkSet chunkSet; // The blocks to be set to the chunkExisting private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers @@ -66,18 +60,12 @@ public class ChunkHolder> implements IQueueChunk { this.delegate = delegate; } + private static final AtomicBoolean recycleWarning = new AtomicBoolean(false); @Override - public synchronized void recycle() { - calledLock.lock(); - delegate = NULL; - if (chunkSet != null) { - chunkSet.recycle(); - chunkSet = null; + public void recycle() { + if (!recycleWarning.getAndSet(true)) { + LOGGER.warn("ChunkHolder should not be recycled.", new Exception()); } - chunkExisting = null; - extent = null; - POOL.offer(this); - calledLock.unlock(); } public long initAge() { @@ -88,68 +76,39 @@ public class ChunkHolder> implements IQueueChunk { return delegate; } - /** - * If the chunk is currently being "called", this method will block until completed. - */ - private void checkAndWaitOnCalledLock() { - if (!calledLock.tryLock()) { - calledLock.lock(); - } - calledLock.unlock(); - } - @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - checkAndWaitOnCalledLock(); - return delegate.set(this).setTile(x, y, z, tag); - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - checkAndWaitOnCalledLock(); - return delegate.set(this).getTile(x, y, z); - } - - @Override - public void setEntity(CompoundTag tag) { - checkAndWaitOnCalledLock(); - delegate.set(this).setEntity(tag); + public void entity(final FaweCompoundTag tag) { + delegate.set(this).entity(tag); } @Override public void removeEntity(UUID uuid) { - checkAndWaitOnCalledLock(); delegate.set(this).removeEntity(uuid); } @Override public Set getEntityRemoves() { - checkAndWaitOnCalledLock(); return delegate.set(this).getEntityRemoves(); } @Override public BiomeType[][] getBiomes() { - checkAndWaitOnCalledLock(); // Uses set as this method is only used to retrieve biomes that have been set to the extent/chunk. return delegate.set(this).getBiomes(); } @Override public char[][] getLight() { - checkAndWaitOnCalledLock(); return delegate.set(this).getLight(); } @Override public char[][] getSkyLight() { - checkAndWaitOnCalledLock(); return delegate.set(this).getSkyLight(); } @Override public void setBlocks(int layer, char[] data) { - checkAndWaitOnCalledLock(); delegate.set(this).setBlocks(layer, data); } @@ -174,12 +133,10 @@ public class ChunkHolder> implements IQueueChunk { @Override public void setFastMode(boolean fastmode) { - checkAndWaitOnCalledLock(); this.fastmode = fastmode; } public void setBitMask(int bitMask) { - checkAndWaitOnCalledLock(); this.bitMask = bitMask; } @@ -189,7 +146,6 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean hasBiomes(final int layer) { - checkAndWaitOnCalledLock(); // No need to go through delegate. hasBiomes is SET only. return chunkSet != null && chunkSet.hasBiomes(layer); } @@ -199,15 +155,9 @@ public class ChunkHolder> implements IQueueChunk { } @Override - public CompoundTag getEntity(UUID uuid) { - checkAndWaitOnCalledLock(); - return delegate.get(this).getEntity(uuid); - } - - @Override - public void setCreateCopy(boolean createCopy) { - checkAndWaitOnCalledLock(); + public int setCreateCopy(boolean createCopy) { this.createCopy = createCopy; + return -1; } @Override @@ -217,19 +167,16 @@ public class ChunkHolder> implements IQueueChunk { @Override public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - checkAndWaitOnCalledLock(); delegate.setLightingToGet(this, lighting); } @Override public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - checkAndWaitOnCalledLock(); delegate.setSkyLightingToGet(this, lighting); } @Override public void setHeightmapToGet(HeightMapType type, int[] data) { - checkAndWaitOnCalledLock(); delegate.setHeightmapToGet(this, type, data); } @@ -254,7 +201,6 @@ public class ChunkHolder> implements IQueueChunk { } public void flushLightToGet() { - checkAndWaitOnCalledLock(); delegate.flushLightToGet(this); } @@ -919,21 +865,8 @@ public class ChunkHolder> implements IQueueChunk { } }; - @Override - public Map getTiles() { - checkAndWaitOnCalledLock(); - return delegate.get(this).getTiles(); - } - - @Override - public Set getEntities() { - checkAndWaitOnCalledLock(); - return delegate.get(this).getEntities(); - } - @Override public boolean hasSection(int layer) { - checkAndWaitOnCalledLock(); return chunkExisting != null && chunkExisting.hasSection(layer); } @@ -958,6 +891,7 @@ public class ChunkHolder> implements IQueueChunk { if (result) { delegate = NULL; chunkExisting = null; + chunkSet.recycle(); chunkSet = null; return true; } @@ -985,18 +919,21 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean isEmpty() { - checkAndWaitOnCalledLock(); return chunkSet == null || chunkSet.isEmpty(); } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { + return delegate.set(this).tile(x, y, z, tag); + } + /** * Get or create the existing part of this chunk. */ public final IChunkGet getOrCreateGet() { - checkAndWaitOnCalledLock(); if (chunkExisting == null) { chunkExisting = newWrappedGet(); - chunkExisting.trim(false); + chunkExisting.trim(MemUtil.isMemoryLimited()); } return chunkExisting; } @@ -1005,7 +942,6 @@ public class ChunkHolder> implements IQueueChunk { * Get or create the settable part of this chunk. */ public final IChunkSet getOrCreateSet() { - checkAndWaitOnCalledLock(); if (chunkSet == null) { chunkSet = newWrappedSet(); } @@ -1026,7 +962,7 @@ public class ChunkHolder> implements IQueueChunk { * - The purpose of wrapping is to allow different extents to intercept / alter behavior * - e.g., caching, optimizations, filtering */ - private synchronized IChunkGet newWrappedGet() { + private IChunkGet newWrappedGet() { return extent.getCachedGet(chunkX, chunkZ); } @@ -1048,44 +984,57 @@ public class ChunkHolder> implements IQueueChunk { @Override public synchronized T call() { - calledLock.lock(); if (chunkSet != null && !chunkSet.isEmpty()) { - this.delegate = GET; chunkSet.setBitMask(bitMask); + IChunkSet copy = chunkSet.createCopy(); + return this.call(copy, () -> { + // Do nothing + }); + } + return null; + } + + /** + * This method should never be called from outside ChunkHolder + */ + @Override + public synchronized T call(IChunkSet set, Runnable finalize) { + if (set != null) { + IChunkGet get = getOrCreateGet(); try { - IChunkSet copy = chunkSet.createCopy(); - chunkSet = null; - return this.call(copy, () -> { - // Do nothing - }); - } catch (Throwable t) { - calledLock.unlock(); - throw t; + get.lockCall(); + trackExtent(); + boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor); + final int copyKey = get.setCreateCopy(postProcess); + final IChunkSet iChunkSet = getExtent().processSet(this, get, set); + Runnable finalizer; + if (postProcess) { + finalizer = () -> { + getExtent().postProcess(this, get.getCopy(copyKey), iChunkSet); + finalize.run(); + }; + } else { + finalizer = finalize; + } + return get.call(set, finalizer); + } finally { + get.unlockCall(); + untrackExtent(); } } return null; } - @Override - public synchronized T call(IChunkSet set, Runnable finalize) { - if (set != null) { - IChunkGet get = getOrCreateGet(); - boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor); - get.setCreateCopy(postProcess); - final IChunkSet iChunkSet = getExtent().processSet(this, get, set); - Runnable finalizer; - if (postProcess) { - finalizer = () -> { - getExtent().postProcess(this, get.getCopy(), iChunkSet); - finalize.run(); - }; - } else { - finalizer = finalize; - } - calledLock.unlock(); - return get.call(set, finalizer); - } - return null; + // "call" can be called by QueueHandler#blockingExecutor. In such case, we still want the other thread + // to use this SingleThreadQueueExtent. Otherwise, many threads might end up locking on **one** STQE. + // This way, locking is spread across multiple STQEs, allowing for better performance + + private void trackExtent() { + ParallelQueueExtent.setCurrentExtent(extent); + } + + private void untrackExtent() { + ParallelQueueExtent.clearCurrentExtent(); } /** @@ -1107,106 +1056,109 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - checkAndWaitOnCalledLock(); return delegate.setBiome(this, x, y, z, biome); } @Override public > boolean setBlock(int x, int y, int z, B block) { - checkAndWaitOnCalledLock(); return delegate.setBlock(this, x, y, z, block); } @Override public BiomeType getBiomeType(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBiome(this, x, y, z); } @Override public BlockState getBlock(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBlock(this, x, y, z); } + @Override + public Map tiles() { + return delegate.get(this).tiles(); + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return delegate.get(this).tile(x, y, z); + } + + @Override + public Collection entities() { + return delegate.get(this).entities(); + } + @Override public BaseBlock getFullBlock(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getFullBlock(this, x, y, z); } @Override public void setSkyLight(int x, int y, int z, int value) { - checkAndWaitOnCalledLock(); delegate.setSkyLight(this, x, y, z, value); } @Override public void setHeightMap(HeightMapType type, int[] heightMap) { - checkAndWaitOnCalledLock(); delegate.setHeightMap(this, type, heightMap); } @Override public void removeSectionLighting(int layer, boolean sky) { - checkAndWaitOnCalledLock(); delegate.removeSectionLighting(this, layer, sky); } @Override public void setFullBright(int layer) { - checkAndWaitOnCalledLock(); delegate.setFullBright(this, layer); } @Override public void setBlockLight(int x, int y, int z, int value) { - checkAndWaitOnCalledLock(); delegate.setBlockLight(this, x, y, z, value); } @Override public void setLightLayer(int layer, char[] toSet) { - checkAndWaitOnCalledLock(); delegate.setLightLayer(this, layer, toSet); } @Override public void setSkyLightLayer(int layer, char[] toSet) { - checkAndWaitOnCalledLock(); delegate.setSkyLightLayer(this, layer, toSet); } @Override public int getSkyLight(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getSkyLight(this, x, y, z); } @Override public int getEmittedLight(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getEmittedLight(this, x, y, z); } @Override public int getBrightness(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBrightness(this, x, y, z); } @Override public int getOpacity(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getOpacity(this, x, y, z); } @Override public int[] getHeightMap(HeightMapType type) { - checkAndWaitOnCalledLock(); return delegate.getHeightMap(this, type); } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return delegate.get(this).entity(uuid); + } + public interface IBlockDelegate { > IChunkGet get(ChunkHolder chunk); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java index 99757a513..14107e83a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java @@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.chunk; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -16,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -53,13 +54,11 @@ public final class NullChunk implements IQueueChunk { return false; } - public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) { + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { return false; } - public void setEntity(@Nonnull CompoundTag tag) { - } - public void removeEntity(@Nonnull UUID uuid) { } @@ -112,6 +111,10 @@ public final class NullChunk implements IQueueChunk { public void setFullBright(int layer) { } + @Override + public void entity(final FaweCompoundTag tag) { + } + public void removeSectionLighting(int layer, boolean sky) { } @@ -147,25 +150,26 @@ public final class NullChunk implements IQueueChunk { return BlockTypes.__RESERVED__.getDefaultState(); } + @Override + public Map tiles() { + return Collections.emptyMap(); + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return null; + } + + @Override + public Collection entities() { + return Collections.emptyList(); + } + @Nonnull public BaseBlock getFullBlock(int x, int y, int z) { return BlockTypes.__RESERVED__.getDefaultState().toBaseBlock(); } - @Nonnull - public Map getTiles() { - return Collections.emptyMap(); - } - - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return null; - } - - @Nonnull - public Set getEntities() { - return Collections.emptySet(); - } @Nullable public char[] load(int layer) { @@ -178,13 +182,9 @@ public final class NullChunk implements IQueueChunk { return null; } - @Nullable - public CompoundTag getEntity(@Nonnull UUID uuid) { - return null; - } - @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -229,6 +229,11 @@ public final class NullChunk implements IQueueChunk { return null; } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return null; + } + public boolean trim(boolean aggressive) { return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java index 7a74ed8ac..672ecfc93 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java @@ -111,8 +111,8 @@ public class AsyncPreloader implements Preloader, Runnable { while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid BlockVector2 chunk = chunksIter.next(); if (Settings.settings().REGION_RESTRICTIONS_OPTIONS.RESTRICT_TO_SAFE_RANGE) { - int x = chunk.getX(); - int z = chunk.getZ(); + int x = chunk.x(); + int z = chunk.z(); // if any chunk coord is outside 30 million blocks if (x > 1875000 || z > 1875000 || x < -1875000 || z < -1875000) { continue; @@ -130,7 +130,7 @@ public class AsyncPreloader implements Preloader, Runnable { } private void queueLoad(World world, BlockVector2 chunk) { - world.checkLoadedChunk(BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4)); + world.checkLoadedChunk(BlockVector3.at(chunk.x() << 4, 0, chunk.z() << 4)); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/FuzzyRegion.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/FuzzyRegion.java index 58061bfa0..e080baeaf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/FuzzyRegion.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/FuzzyRegion.java @@ -52,7 +52,7 @@ public class FuzzyRegion extends AbstractRegion { */ public void select(BlockVector3 position) { RecursiveVisitor search = new RecursiveVisitor(mask, p -> { - setMinMax(p.getBlockX(), p.getBlockY(), p.getBlockZ()); + setMinMax(p.x(), p.y(), p.z()); return true; }, 256, extent.getMinY(), extent.getMaxY(), extent); search.setVisited(set); @@ -120,7 +120,7 @@ public class FuzzyRegion extends AbstractRegion { @Override public boolean contains(BlockVector3 position) { - return contains(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return contains(position.x(), position.y(), position.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java index 03dd750a5..675e8efb6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java @@ -71,13 +71,13 @@ public class PolyhedralRegion extends AbstractRegion { public PolyhedralRegion(PolyhedralRegion region) { this(region.world); vertices.addAll(region.vertices); - triangles.addAll(region.triangles); + region.triangles.forEach(triangle -> triangles.add(triangle.clone())); vertexBacklog.addAll(region.vertexBacklog); minimumPoint = region.minimumPoint; maximumPoint = region.maximumPoint; centerAccum = region.centerAccum; - lastTriangle = region.lastTriangle; + lastTriangle = lastTriangle == null ? null : region.lastTriangle.clone(); } /** @@ -261,27 +261,27 @@ public class PolyhedralRegion extends AbstractRegion { if (!isDefined()) { return false; } - final int x = position.getBlockX(); - final int y = position.getBlockY(); - final int z = position.getBlockZ(); + final int x = position.x(); + final int y = position.y(); + final int z = position.z(); final BlockVector3 min = getMinimumPoint(); final BlockVector3 max = getMaximumPoint(); - if (x < min.getBlockX()) { + if (x < min.x()) { return false; } - if (x > max.getBlockX()) { + if (x > max.x()) { return false; } - if (z < min.getBlockZ()) { + if (z < min.z()) { return false; } - if (z > max.getBlockZ()) { + if (z > max.z()) { return false; } - if (y < min.getBlockY()) { + if (y < min.y()) { return false; } - if (y > max.getBlockY()) { + if (y > max.y()) { return false; } return containsRaw(position); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/RegionWrapper.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/RegionWrapper.java index e382583aa..40d0075e5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/RegionWrapper.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/RegionWrapper.java @@ -44,12 +44,12 @@ public class RegionWrapper extends CuboidRegion { public RegionWrapper(final BlockVector3 pos1, final BlockVector3 pos2) { super(pos1, pos2); - this.minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); - this.minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); - this.maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); - this.maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); - this.minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); - this.maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()); + this.minX = Math.min(pos1.x(), pos2.x()); + this.minZ = Math.min(pos1.z(), pos2.z()); + this.maxX = Math.max(pos1.x(), pos2.x()); + this.maxZ = Math.max(pos1.z(), pos2.z()); + this.minY = Math.min(pos1.y(), pos2.y()); + this.maxY = Math.max(pos1.y(), pos2.y()); } public static RegionWrapper GLOBAL() { @@ -61,12 +61,12 @@ public class RegionWrapper extends CuboidRegion { super.recalculate(); BlockVector3 pos1 = getMinimumPoint(); BlockVector3 pos2 = getMaximumPoint(); - this.minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); - this.minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); - this.maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); - this.maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); - this.minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); - this.maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()); + this.minX = Math.min(pos1.x(), pos2.x()); + this.minZ = Math.min(pos1.z(), pos2.z()); + this.maxX = Math.max(pos1.x(), pos2.x()); + this.maxZ = Math.max(pos1.z(), pos2.z()); + this.minY = Math.min(pos1.y(), pos2.y()); + this.maxY = Math.max(pos1.y(), pos2.y()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java index 46e934bee..1d96d5f95 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java @@ -7,10 +7,14 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.polyhedron.Edge; -public class Triangle { +public class Triangle implements Cloneable { public static double RADIUS = 0.5; + private final BlockVector3 pos1; + private final BlockVector3 pos2; + private final BlockVector3 pos3; + private final double[][] verts = new double[3][3]; private final double[] center = new double[3]; private final double[] radius = new double[3]; @@ -28,9 +32,12 @@ public class Triangle { private final double b; public Triangle(BlockVector3 pos1, BlockVector3 pos2, BlockVector3 pos3) { - verts[0] = new double[]{pos1.getBlockX(), pos1.getBlockY(), pos1.getBlockZ()}; - verts[1] = new double[]{pos2.getBlockX(), pos2.getBlockY(), pos2.getBlockZ()}; - verts[2] = new double[]{pos3.getBlockX(), pos3.getBlockY(), pos3.getBlockZ()}; + this.pos1 = pos1; + this.pos2 = pos2; + this.pos3 = pos3; + verts[0] = new double[]{pos1.x(), pos1.y(), pos1.z()}; + verts[1] = new double[]{pos2.x(), pos2.y(), pos2.z()}; + verts[2] = new double[]{pos3.x(), pos3.y(), pos3.z()}; radius[0] = RADIUS; radius[1] = RADIUS; radius[2] = RADIUS; @@ -72,9 +79,9 @@ public class Triangle { } public boolean contains(BlockVector3 pos) { - center[0] = pos.getBlockX() + RADIUS; - center[1] = pos.getBlockY() + RADIUS; - center[2] = pos.getBlockZ() + RADIUS; + center[0] = pos.x() + RADIUS; + center[1] = pos.y() + RADIUS; + center[2] = pos.z() + RADIUS; return overlaps(center, radius, verts); } @@ -290,4 +297,9 @@ public class Triangle { return dot(normal, vmax) >= 0.0f; } + @Override + public Triangle clone() { + return new Triangle(pos1, pos2, pos3); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/filter/CuboidRegionFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/filter/CuboidRegionFilter.java index d354eae3b..72413e115 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/filter/CuboidRegionFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/filter/CuboidRegionFilter.java @@ -19,10 +19,10 @@ public abstract class CuboidRegionFilter implements RegionFilter { public abstract void calculateRegions(); public void add(BlockVector2 pos1, BlockVector2 pos2) { - int ccx1 = pos1.getBlockX() >> 9; - int ccz1 = pos1.getBlockZ() >> 9; - int ccx2 = pos2.getBlockX() >> 9; - int ccz2 = pos2.getBlockZ() >> 9; + int ccx1 = pos1.x() >> 9; + int ccz1 = pos1.z() >> 9; + int ccx2 = pos2.x() >> 9; + int ccz2 = pos2.z() >> 9; for (int x = ccx1; x <= ccx2; x++) { for (int z = ccz1; z <= ccz2; z++) { if (!occupiedRegions.containsKey(x, z)) { @@ -39,10 +39,10 @@ public abstract class CuboidRegionFilter implements RegionFilter { } } } - int cx1 = pos1.getBlockX() >> 4; - int cz1 = pos1.getBlockZ() >> 4; - int cx2 = pos2.getBlockX() >> 4; - int cz2 = pos2.getBlockZ() >> 4; + int cx1 = pos1.x() >> 4; + int cz1 = pos1.z() >> 4; + int cx2 = pos2.x() >> 4; + int cz2 = pos2.z() >> 4; for (int chunkZ = cz1; chunkZ <= cz2; chunkZ++) { for (int chunkX = cx1; chunkX <= cx2; chunkX++) { unoccupiedChunks.remove(chunkX, chunkZ); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/registry/state/PropertyKey.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/registry/state/PropertyKey.java index baba00a6b..0147d0e91 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/registry/state/PropertyKey.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/registry/state/PropertyKey.java @@ -137,4 +137,9 @@ public class PropertyKey implements Comparable { return Integer.compare(this.id, o.id); } + @Override + public String toString() { + return "PropertyKey[" + getName() + "]"; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/BrushCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/BrushCache.java index afab331a7..762929400 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/BrushCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/BrushCache.java @@ -82,7 +82,7 @@ public final class BrushCache { } CompoundTag nbt = item.getNbtData(); - Map map; + Map> map; if (nbt == null) { if (tool == null) { item.setNbtData(null); @@ -92,9 +92,10 @@ public final class BrushCache { } else { map = nbt.getValue(); } + item.setNbtData(nbt); brushCache.remove(getKey(item)); CompoundTag display = (CompoundTag) map.get("display"); - Map displayMap; + Map> displayMap; return tool; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ExtentTraverser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ExtentTraverser.java index e7038deaa..6ae147765 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ExtentTraverser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ExtentTraverser.java @@ -51,11 +51,10 @@ public class ExtentTraverser { return last; } - @SuppressWarnings("unchecked") @Nullable - public U findAndGet(Class clazz) { - ExtentTraverser traverser = find(clazz); - return (traverser != null) ? (U) traverser.get() : null; + public U findAndGet(Class clazz) { + ExtentTraverser traverser = find(clazz); + return (traverser != null) ? traverser.get() : null; } @SuppressWarnings("unchecked") diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java index 8122a840c..04da475e2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java @@ -34,10 +34,14 @@ import net.jpountz.lz4.LZ4Compressor; import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4FastDecompressor; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; @@ -56,6 +60,9 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; @@ -70,6 +77,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -91,6 +99,10 @@ import static java.lang.System.arraycopy; public class MainUtil { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static final String CURL_USER_AGENT = "curl/8.1.1"; + private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.NORMAL) + .build(); public static List filter(String prefix, List suggestions) { if (prefix.isEmpty()) { @@ -206,7 +218,7 @@ public class MainUtil { // } else if (changeSet instanceof CPUOptimizedChangeSet) { // return changeSet.size() + 32; } else if (changeSet != null) { - return changeSet.size() * 128L; + return changeSet.longSize() * 128; // Approx } else { return 0; } @@ -413,10 +425,12 @@ public class MainUtil { * @param y New Y coordinate * @param z New Z coordinate * @return New tag + * @deprecated use {@link NbtUtils#withPosition} instead */ @Nonnull + @Deprecated(forRemoval = true, since = "2.11.2") public static CompoundTag setPosition(@Nonnull CompoundTag tag, int x, int y, int z) { - Map value = new HashMap<>(tag.getValue()); + Map> value = new HashMap<>(tag.getValue()); value.put("x", new IntTag(x)); value.put("y", new IntTag(y)); value.put("z", new IntTag(z)); @@ -429,19 +443,21 @@ public class MainUtil { * @param tag Tag to copy * @param entity Entity * @return New tag + * @deprecated use {@link NbtUtils#withEntityInfo(LinCompoundTag, Entity)} instead */ @Nonnull + @Deprecated(forRemoval = true, since = "2.11.2") public static CompoundTag setEntityInfo(@Nonnull CompoundTag tag, @Nonnull Entity entity) { - Map map = new HashMap<>(tag.getValue()); - map.put("Id", new StringTag(entity.getState().getType().getId())); + Map> map = new HashMap<>(tag.getValue()); + map.put("Id", new StringTag(entity.getState().getType().id())); ListTag pos = (ListTag) map.get("Pos"); if (pos != null) { Location loc = entity.getLocation(); // Create a copy, because the list is immutable... List posList = new ArrayList<>(pos.getValue()); - posList.set(0, new DoubleTag(loc.getX())); - posList.set(1, new DoubleTag(loc.getY())); - posList.set(2, new DoubleTag(loc.getZ())); + posList.set(0, new DoubleTag(loc.x())); + posList.set(1, new DoubleTag(loc.y())); + posList.set(2, new DoubleTag(loc.z())); map.put("Pos", new ListTag(pos.getType(), posList)); } return new CompoundTag(map); @@ -519,12 +535,57 @@ public class MainUtil { return destFile; } - public static BufferedImage readImage(InputStream in) throws IOException { - return MainUtil.toRGB(ImageIO.read(in)); + public static BufferedImage readImage(InputStream stream) throws IOException { + final ImageInputStream imageStream = ImageIO.createImageInputStream(stream); + if (imageStream == null) { + throw new IOException("Can't find suitable ImageInputStream"); + } + Iterator iter = ImageIO.getImageReaders(imageStream); + if (!iter.hasNext()) { + throw new IOException("Could not get image reader from stream."); + } + ImageReader reader = iter.next(); + ImageReadParam param = reader.getDefaultReadParam(); + reader.setInput(imageStream, true, true); + BufferedImage bi; + try { + bi = reader.read(0, param); + } finally { + reader.dispose(); + stream.close(); + imageStream.close(); + } + return MainUtil.toRGB(bi); } public static BufferedImage readImage(URL url) throws IOException { - return readImage(url.openStream()); + try (final InputStream stream = readImageStream(url.toURI())) { + return readImage(stream); + } catch (URISyntaxException e) { + throw new IOException("failed to parse url to uri reference", e); + } + } + + public static InputStream readImageStream(final URI uri) throws IOException { + try { + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + + if (uri.getHost().equalsIgnoreCase("i.imgur.com")) { + requestBuilder = requestBuilder.setHeader("User-Agent", CURL_USER_AGENT); + } + + final HttpResponse response = HTTP_CLIENT.send( + requestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream() + ); + final InputStream body = response.body(); + if (response.statusCode() > 299) { + throw new IOException("Expected 2xx as response code, but received " + response.statusCode()); + } + return body; + } catch (InterruptedException e) { + throw new IOException("request was interrupted", e); + } } public static BufferedImage readImage(File file) throws IOException { @@ -645,7 +706,7 @@ public class MainUtil { public static File resolve(File dir, String filename, @Nullable ClipboardFormat format, boolean allowDir) { if (format != null) { - if (!filename.matches(".*\\.[\\w].*")) { + if (!filename.matches(".*\\.\\w.*")) { filename = filename + "." + format.getPrimaryFileExtension(); } return MainUtil.resolveRelative(new File(dir, filename)); @@ -656,6 +717,12 @@ public class MainUtil { return file; } } + if (filename.matches(".*\\.\\w.*")) { + File file = MainUtil.resolveRelative(new File(dir, filename)); + if (file.exists()) { + return file; + } + } for (ClipboardFormat f : ClipboardFormats.getAll()) { File file = MainUtil.resolveRelative(new File(dir, filename + "." + f.getPrimaryFileExtension())); if (file.exists()) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java index 7abb51284..07a047360 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java @@ -1,18 +1,30 @@ package com.fastasyncworldedit.core.util; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagType; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; +import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; +import java.util.UUID; -public class NbtUtils { +public final class NbtUtils { + + private NbtUtils() { + } /** * Get child tag of a NBT structure. @@ -23,9 +35,9 @@ public class NbtUtils { * @return child tag * @throws InvalidFormatException if the format of the items is invalid */ - public static T getChildTag(CompoundBinaryTag tag, String key, BinaryTagType expected) throws + public static T getChildTag(LinCompoundTag tag, String key, LinTagType expected) throws InvalidFormatException { - BinaryTag childTag = tag.get(key); + LinTag childTag = tag.value().get(key); if (childTag == null) { throw new InvalidFormatException("Missing a \"" + key + "\" tag"); } @@ -48,36 +60,170 @@ public class NbtUtils { * @throws InvalidFormatException if the format of the items is invalid * @since 2.1.0 */ - public static int getInt(CompoundBinaryTag tag, String key) throws InvalidFormatException { - BinaryTag childTag = tag.get(key); + public static int getInt(LinCompoundTag tag, String key) throws InvalidFormatException { + LinTag childTag = tag.value().get(key); if (childTag == null) { throw new InvalidFormatException("Missing a \"" + key + "\" tag"); } - BinaryTagType type = childTag.type(); - if (type == BinaryTagTypes.INT) { - return ((IntBinaryTag) childTag).intValue(); + LinTagType type = childTag.type(); + if (type == LinTagType.intTag()) { + return ((LinIntTag) childTag).value(); } - if (type == BinaryTagTypes.BYTE) { - return ((ByteBinaryTag) childTag).intValue(); + if (type == LinTagType.byteTag()) { + return ((LinByteTag) childTag).value(); } - if (type == BinaryTagTypes.SHORT) { - return ((ShortBinaryTag) childTag).intValue(); + if (type == LinTagType.shortTag()) { + return ((LinShortTag) childTag).value(); } throw new InvalidFormatException(key + " tag is not of int, short or byte tag type."); } /** - * Get a mutable map of the values stored inside a {@link CompoundBinaryTag} + * Get a mutable map of the values stored inside a {@link LinCompoundTag} * - * @param tag {@link CompoundBinaryTag} to get values for + * @param tag {@link LinCompoundTag} to get values for * @return Mutable map of values * @since 2.1.0 */ - public static Map getCompoundBinaryTagValues(CompoundBinaryTag tag) { - Map value = new HashMap<>(); - tag.forEach((e) -> value.put(e.getKey(), e.getValue())); + public static Map> getLinCompoundTagValues(LinCompoundTag tag) { + Map> value = new HashMap<>(); + value.putAll(tag.value()); return value; } + /** + * Tries to extract UUID information from a compound tag + * + * @param compoundTag the compound tag to extract uuid information from + * @return the extracted UUID + * @since 2.11.2 + */ + public static UUID uuid(FaweCompoundTag compoundTag) { + final LinCompoundTag linTag = compoundTag.linTag(); + { + final LinIntArrayTag uuidTag = linTag.findTag("UUID", LinTagType.intArrayTag()); + if (uuidTag != null) { + int[] arr = uuidTag.value(); + return new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL)); + } + } + { + final LinLongTag uuidMostTag = linTag.findTag("UUIDMost", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("UUIDLeast", LinTagType.longTag()).valueAsLong()); + } + } + { + final LinLongTag uuidMostTag = linTag.findTag("WorldUUIDMost", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("WorldUUIDLeast", LinTagType.longTag()).valueAsLong()); + } + + } + { + final LinLongTag uuidMostTag = linTag.findTag("PersistentIDMSB", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("PersistentIDLSB", LinTagType.longTag()).valueAsLong()); + } + + } + throw new IllegalArgumentException("no uuid present"); + + } + + /** + * Create a copy of the tag and modify the (x, y, z) coordinates + * + * @param tag Tag to copy + * @param x New X coordinate + * @param y New Y coordinate + * @param z New Z coordinate + * @return New tag + * @since 2.11.2 + */ + public static @Nonnull LinCompoundTag withPosition(@Nonnull LinCompoundTag tag, int x, int y, int z) { + return tag.toBuilder() + .putInt("x", x) + .putInt("y", y) + .putInt("z", z) + .build(); + } + + /** + * Create a copy of the tag and modify the (x, y, z) coordinates + * + * @param tag Tag to copy + * @param x New X coordinate + * @param y New Y coordinate + * @param z New Z coordinate + * @return New tag + * @since 2.11.2 + */ + public static @Nonnull FaweCompoundTag withPosition(@Nonnull FaweCompoundTag tag, int x, int y, int z) { + return FaweCompoundTag.of(withPosition(tag.linTag(), x, y, z)); + } + + /** + * {@return a copy of the given tag with the Id and the Pos of the given entity} + * + * @param tag the tag to copy + * @param entity the entity to use the Id and the Pos from + * @since 2.11.2 + */ + public static @Nonnull LinCompoundTag withEntityInfo(@Nonnull LinCompoundTag tag, @Nonnull Entity entity) { + final LinCompoundTag.Builder builder = tag.toBuilder() + .putString("Id", entity.getState().getType().id()); + LinListTag pos = tag.findListTag("Pos", LinTagType.doubleTag()); + if (pos != null) { // TODO why only if pos != null? + Location loc = entity.getLocation(); + final LinListTag newPos = LinListTag.builder(LinTagType.doubleTag()) + .add(LinDoubleTag.of(loc.x())) + .add(LinDoubleTag.of(loc.y())) + .add(LinDoubleTag.of(loc.z())) + .build(); + builder.put("Pos", newPos); + } + return builder.build(); + } + + /** + * Adds a UUID to the given map + * + * @param map the map to insert to + * @param uuid the uuid to insert + * @since 2.11.2 + */ + public static void addUUIDToMap(Map> map, UUID uuid) { + int[] uuidArray = new int[4]; + uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32); + uuidArray[1] = (int) uuid.getMostSignificantBits(); + uuidArray[2] = (int) (uuid.getLeastSignificantBits() >> 32); + uuidArray[3] = (int) uuid.getLeastSignificantBits(); + map.put("UUID", LinIntArrayTag.of(uuidArray)); + + map.put("UUIDMost", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("UUIDLeast", LinLongTag.of(uuid.getLeastSignificantBits())); + + map.put("WorldUUIDMost", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("WorldUUIDLeast", LinLongTag.of(uuid.getLeastSignificantBits())); + + map.put("PersistentIDMSB", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("PersistentIDLSB", LinLongTag.of(uuid.getLeastSignificantBits())); + } + + /** + * {@return the position data of the given tag} + * + * @param compoundTag the tag to extract position information from + * @since 2.12.0 + */ + public static Vector3 entityPosition(FaweCompoundTag compoundTag) { + LinListTag pos = compoundTag.linTag().getListTag("Pos", LinTagType.doubleTag()); + double x = pos.get(0).valueAsDouble(); + double y = pos.get(1).valueAsDouble(); + double z = pos.get(2).valueAsDouble(); + return Vector3.at(x, y, z); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ReflectionUtils.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ReflectionUtils.java index 607117535..7b8ffcd2c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ReflectionUtils.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ReflectionUtils.java @@ -4,19 +4,19 @@ import sun.misc.Unsafe; import javax.annotation.Nonnull; import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Comparator; /** * This is an internal class not meant to be used outside the FAWE internals. */ public class ReflectionUtils { + private static final VarHandle REFERENCE_ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(Object[].class); private static Unsafe UNSAFE; static { @@ -33,6 +33,21 @@ public class ReflectionUtils { return t.isInstance(o) ? t.cast(o) : null; } + /** + * Performs CAS on the array element at the given index. + * + * @param array the array in which to compare and set the value + * @param expectedValue the value expected to be at the index + * @param newValue the new value to be set at the index if the expected value matches + * @param index the index at which to compare and set the value + * @param the type of elements in the array + * @return true if the value at the index was successfully updated to the new value, false otherwise + * @see VarHandle#compareAndSet(Object...) + */ + public static boolean compareAndSet(T[] array, T expectedValue, T newValue, int index) { + return REFERENCE_ARRAY_HANDLE.compareAndSet(array, index, expectedValue, newValue); + } + public static void setAccessibleNonFinal(Field field) { // let's make the field accessible field.setAccessible(true); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java index f6f896f56..7c4e7137b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java @@ -929,10 +929,10 @@ public class TextureUtil implements TextureHolder { }.getType(); for (BlockType blockType : BlockTypesCache.values) { - if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) { + if (!blockType.getMaterial().isFullCube() || blockType.id().toLowerCase().contains("shulker")) { continue; } - switch (blockType.getId().toLowerCase(Locale.ROOT)) { + switch (blockType.id().toLowerCase(Locale.ROOT)) { case "slime_block": case "honey_block": case "mob_spawner": @@ -940,7 +940,7 @@ public class TextureUtil implements TextureHolder { continue; } int combined = blockType.getInternalId(); - String id = blockType.getId(); + String id = blockType.id(); String[] split = id.split(":", 2); String name = split.length == 1 ? id : split[1]; String nameSpace = split.length == 1 ? "" : split[0]; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/UpdateNotification.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/UpdateNotification.java index 73ad01361..fdfe7c56c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/UpdateNotification.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/UpdateNotification.java @@ -59,12 +59,12 @@ public class UpdateNotification { Document doc = db.parse(body); faweVersion = doc.getElementsByTagName("lastSuccessfulBuild").item(0).getFirstChild().getTextContent(); FaweVersion faweVersion = Fawe.instance().getVersion(); - if (faweVersion.build == 0 && !faweVersion.snapshot) { + if (faweVersion.build == 0 && faweVersion.snapshot) { LOGGER.warn("You are using a snapshot or a custom version of FAWE. This is not an official build distributed " + "via https://www.spigotmc.org/resources/13932/"); return; } - if (faweVersion.build < Integer.parseInt(UpdateNotification.faweVersion)) { + if (faweVersion.snapshot && faweVersion.build < Integer.parseInt(UpdateNotification.faweVersion)) { hasUpdate = true; int versionDifference = Integer.parseInt(UpdateNotification.faweVersion) - faweVersion.build; LOGGER.warn( diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/WEManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/WEManager.java index 17b7882f2..00ededf1a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/WEManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/WEManager.java @@ -32,7 +32,7 @@ public class WEManager { * @deprecated Use {@link #weManager()} instead. */ @Deprecated(forRemoval = true, since = "2.0.0") - public static WEManager IMP = new WEManager(); + public static WEManager IMP = weManager(); private final ArrayDeque managers = new ArrayDeque<>(); /** @@ -183,8 +183,8 @@ public class WEManager { BlockVector3 rg2P1 = region2.getMinimumPoint(); BlockVector3 rg2P2 = region2.getMaximumPoint(); - return rg1P1.getBlockX() <= rg2P2.getBlockX() && rg1P2.getBlockX() >= rg2P1.getBlockX() - && rg1P1.getBlockZ() <= rg2P2.getBlockZ() && rg1P2.getBlockZ() >= rg2P1.getBlockZ(); + return rg1P1.x() <= rg2P2.x() && rg1P2.x() >= rg2P1.x() + && rg1P1.z() <= rg2P2.z() && rg1P2.z() >= rg2P1.z(); } public boolean regionContains(Region selection, HashSet mask) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaResponse.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaResponse.java new file mode 100644 index 000000000..821751c2a --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaResponse.java @@ -0,0 +1,4 @@ +package com.fastasyncworldedit.core.util.arkitektonika; + +public record ArkitektonikaResponse(String downloadKey, String deletionKey) { +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaSchematicUploader.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaSchematicUploader.java new file mode 100644 index 000000000..152bca058 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/arkitektonika/ArkitektonikaSchematicUploader.java @@ -0,0 +1,58 @@ +package com.fastasyncworldedit.core.util.arkitektonika; + +import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareMetadata; +import com.sk89q.worldedit.extent.clipboard.io.share.ShareOutputProvider; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.UUID; + +public class ArkitektonikaSchematicUploader { + + private static final String BOUNDARY_IDENTIFIER = "--"; + private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient(); + private final String apiUrl; + + public ArkitektonikaSchematicUploader(String apiUrl) { + this.apiUrl = apiUrl.endsWith("/") ? apiUrl.substring(0, apiUrl.length() - 1) : apiUrl; + } + + public ArkitektonikaResponse uploadBlocking(ClipboardShareMetadata meta, ShareOutputProvider provider) throws IOException, + InterruptedException { + String boundary = UUID.randomUUID().toString(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + provider.writeTo(outputStream); + + final HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.concat( + HttpRequest.BodyPublishers.ofString(BOUNDARY_IDENTIFIER + boundary + "\r\n"), + HttpRequest.BodyPublishers.ofString("Content-Disposition: form-data; name=\"schematic\"; filename=\"" + meta.name() + "." + meta.format().getPrimaryFileExtension() + "\"\r\n\r\n"), + HttpRequest.BodyPublishers.ofByteArray(outputStream.toByteArray()), + HttpRequest.BodyPublishers.ofString("\r\n" + BOUNDARY_IDENTIFIER + boundary + BOUNDARY_IDENTIFIER) + ); + + final HttpResponse response = HTTP_CLIENT.send(HttpRequest.newBuilder() + .uri(URI.create(this.apiUrl + "/upload")) + .header("Content-Type", "multipart/form-data; boundary=\"" + boundary + "\"") + .POST(bodyPublisher).build(), HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200) { + throw new FaweException(TextComponent + .of("Arkitektonika returned status code " + response.statusCode()) + .color(TextColor.RED)); + } + JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject(); + return new ArkitektonikaResponse( + json.get("download_key").getAsString(), + json.get("delete_key").getAsString() + ); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockSet.java index 0706a39d2..06e7d7cff 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockSet.java @@ -35,7 +35,7 @@ public abstract class BlockSet extends AbstractRegion { @Override public boolean contains(BlockVector3 obj) { - return contains(obj.getX(), obj.getY(), obj.getZ()); + return contains(obj.x(), obj.y(), obj.z()); } protected final int lowestBit(long bitBuffer) { @@ -71,11 +71,11 @@ public abstract class BlockSet extends AbstractRegion { @Override public boolean add(BlockVector3 p) { - return add(p.getX(), p.getY(), p.getZ()); + return add(p.x(), p.y(), p.z()); } public boolean remove(BlockVector3 p) { - return remove(p.getX(), p.getY(), p.getZ()); + return remove(p.x(), p.y(), p.z()); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockVector3Set.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockVector3Set.java index 881aaf9f3..8bf9463f9 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockVector3Set.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/BlockVector3Set.java @@ -9,29 +9,80 @@ import java.util.Set; public interface BlockVector3Set extends Set { + /** + * Get the appropriate {@link BlockVector3Set} implementation for the given region. Either {@link LocalBlockVectorSet} or + * {@link BlockVectorSet}. Sets the offset if using {@link LocalBlockVectorSet}. + * + * @param region Region to get for + * @return Appropriate {@link BlockVector3Set} implementation + */ static BlockVector3Set getAppropriateVectorSet(Region region) { BlockVector3 max = region.getMaximumPoint(); BlockVector3 min = region.getMinimumPoint(); - BlockVector3 size = region.getDimensions(); - if (size.getBlockX() > 2048 || size.getBlockZ() > 2048 || size.getBlockY() > 512) { + BlockVector3Set set = getAppropriateVectorSet(region.getDimensions()); + // Set default offset as many operations utilising a region are likely to start in a corner, this initialising the + // LocalBlockVectorSet poorly + // This needs to be ceiling as LocalBlockVector extends 1 block further "negative" + int offsetX = (int) Math.ceil((min.x() + max.x()) / 2d); + int offsetZ = (int) Math.ceil((min.z() + max.z()) / 2d); + int offsetY; + if (region.getMinimumY() < -128 || region.getMaximumY() > 320) { + offsetY = (min.y() + max.y()) / 2; + } else { + offsetY = 128; + } + set.setOffset(offsetX, offsetY, offsetZ); + return set; + } + + /** + * Get the appropriate {@link BlockVector3Set} implementation for the given dimensions. Either {@link LocalBlockVectorSet} or + * {@link BlockVectorSet}. The offset should be manually set. + * + * @param size Dimensions to get for + * @return Appropriate {@link BlockVector3Set} implementation + */ + static BlockVector3Set getAppropriateVectorSet(BlockVector3 size) { + if (size.x() > 2048 || size.z() > 2048 || size.y() > 512) { return new BlockVectorSet(); } else { - // Set default offset as many operations utilising a region are likely to start in a corner, this initialising the - // LocalBlockVectorSet poorly - // This needs to be ceiling as LocalBlockVector extends 1 block further "negative" - int offsetX = (int) Math.ceil((min.getX() + max.getX()) / 2d); - int offsetZ = (int) Math.ceil((min.getZ() + max.getZ()) / 2d); - int offsetY; - if (region.getMinimumY() < -128 || region.getMaximumY() > 320) { - offsetY = (min.getY() + max.getY()) / 2; - } else { - offsetY = 128; - } - return new LocalBlockVectorSet(offsetX, offsetY, offsetZ); + return new LocalBlockVectorSet(); } } boolean add(int x, int y, int z); boolean contains(int x, int y, int z); + /** + * Set the offset applied to values when storing and reading to keep the values within -1024 to 1023. Uses default y offset + * of 128 to allow -64 -> 320 world height use. + * + * @param x x offset + * @param z z offset + * @since 2.9.2 + */ + void setOffset(int x, int z); + + /** + * Set the offset applied to values when storing and reading to keep the x and z values within -1024 to 1023. Y values + * require keeping withing -256 and 255. + * + * @param x x offset + * @param y y offset + * @param z z offset + * @since 2.9.2 + */ + void setOffset(int x, int y, int z); + + /** + * If a radius is contained by the set + * + * @param x x radius center + * @param y y radius center + * @param z z radius center + * @return if radius is contained by the set + * @since 2.9.2 + */ + boolean containsRadius(int x, int y, int z, int radius); + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/MemBlockSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/MemBlockSet.java index 33fc963c3..68990cad1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/MemBlockSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/MemBlockSet.java @@ -1,7 +1,6 @@ package com.fastasyncworldedit.core.util.collection; import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.math.MutableBlockVector2; import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; @@ -167,9 +166,9 @@ public final class MemBlockSet extends BlockSet { @Override public boolean contains(Object o) { if (o instanceof BlockVector2 other) { - IRow rowx = rows[other.getX() - getChunkOffsetX()]; + IRow rowx = rows[other.x() - getChunkOffsetX()]; if (rowx instanceof RowX) { - return ((RowX) rowx).rows[other.getZ() - getChunkOffsetZ()] instanceof RowZ; + return ((RowX) rowx).rows[other.z() - getChunkOffsetZ()] instanceof RowZ; } } return false; @@ -269,11 +268,11 @@ public final class MemBlockSet extends BlockSet { @Override public boolean contains(Object o) { if (o instanceof BlockVector3 other) { - IRow rowx = rows[other.getX() - getChunkOffsetX()]; + IRow rowx = rows[other.x() - getChunkOffsetX()]; if (rowx instanceof RowX) { - IRow rowz = ((RowX) rowx).rows[other.getZ()]; + IRow rowz = ((RowX) rowx).rows[other.z()]; if (rowz instanceof RowZ) { - return ((RowZ) rowz).rows[other.getY() - (minSectionPosition << 4) - getChunkOffsetZ()] instanceof RowY; + return ((RowZ) rowz).rows[other.y() - (minSectionPosition << 4) - getChunkOffsetZ()] instanceof RowY; } } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java index a157ebd7c..6214777e5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java @@ -33,7 +33,7 @@ public abstract class RandomCollection { public static RandomCollection of(Map weights, SimpleRandom random) { checkNotNull(random); return FastRandomCollection.create(weights, random) - .orElse(new SimpleRandomCollection<>(weights, random)); + .orElseGet(() -> new SimpleRandomCollection<>(weights, random)); } public void setRandom(SimpleRandom random) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java index dc2107559..5b7dca98f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java @@ -36,7 +36,7 @@ public class SimpleRandomCollection extends RandomCollection { @Override public E next(int x, int y, int z) { - return map.ceilingEntry(getRandom().nextDouble(x, y, z) * this.total).getValue(); + return map.ceilingEntry(getRandom().nextDouble(x, y, z, this.total)).getValue(); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/BaseItemAdapter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/BaseItemAdapter.java new file mode 100644 index 000000000..9fbdd88bd --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/BaseItemAdapter.java @@ -0,0 +1,61 @@ +package com.fastasyncworldedit.core.util.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; +import org.enginehub.linbus.format.snbt.LinStringIO; +import org.enginehub.linbus.tree.LinCompoundTag; + +import java.io.IOException; +import java.lang.reflect.Type; + +public final class BaseItemAdapter implements JsonDeserializer, JsonSerializer { + + @Override + public BaseItem deserialize(JsonElement json, Type type, JsonDeserializationContext cont) throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + JsonElement id = jsonObject.get("id"); + if (id != null) { + ItemType itemType = ItemTypes.get(id.getAsString()); + if (itemType == null) { + throw new JsonParseException("Could not parse item type `" + id + "`"); + } + return new BaseItem(itemType); + } + ItemType itemType = cont.deserialize(jsonObject.get("itemType").getAsJsonObject(), ItemType.class); + JsonElement nbt = jsonObject.get("nbt"); + if (nbt == null) { + return new BaseItem(itemType); + } + try { + return new BaseItem( + itemType, + LazyReference.computed(LinCompoundTag.readFrom(LinStringIO.readFromString(nbt.getAsString()))) + ); + } catch (IOException e) { + throw new JsonParseException("Could not deserialize BaseItem", e); + } + } + + @Override + public JsonElement serialize( + final BaseItem baseItem, + final Type type, + final JsonSerializationContext jsonSerializationContext + ) { + JsonObject obj = new JsonObject(); + obj.add("itemType", jsonSerializationContext.serialize(baseItem.getType())); + obj.add("nbt", baseItem.getNbt() == null ? null : new JsonPrimitive(LinStringIO.writeToString(baseItem.getNbt()))); + return obj; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/ItemTypeAdapter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/ItemTypeAdapter.java new file mode 100644 index 000000000..fe684fb8c --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/ItemTypeAdapter.java @@ -0,0 +1,26 @@ +package com.fastasyncworldedit.core.util.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; + +import java.lang.reflect.Type; + +public final class ItemTypeAdapter implements JsonDeserializer { + + @Override + public ItemType deserialize(JsonElement json, Type type, JsonDeserializationContext cont) throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String id = jsonObject.get("id").getAsString(); + ItemType itemType = ItemTypes.get(id); + if (itemType == null) { + throw new JsonParseException("Could not parse item type `" + id + "`"); + } + return itemType; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/RegionSelectorAdapter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/RegionSelectorAdapter.java new file mode 100644 index 000000000..d817185ee --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/gson/RegionSelectorAdapter.java @@ -0,0 +1,33 @@ +package com.fastasyncworldedit.core.util.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.regions.selector.RegionSelectorType; + +import java.lang.reflect.Type; + +public class RegionSelectorAdapter implements JsonDeserializer, JsonSerializer { + + @Override + public RegionSelector deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + RegionSelectorType regionType = RegionSelectorType.valueOf(json.getAsString()); + return regionType.createSelector(); + } + + @Override + public JsonElement serialize(RegionSelector selector, Type type, JsonSerializationContext context) { + RegionSelectorType regionType = RegionSelectorType.getForSelector(selector); + // Cannot nicely deserialize Fuzzy region type + if (regionType == null || regionType == RegionSelectorType.FUZZY) { + return null; + } + return new JsonPrimitive(regionType.toString()); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/image/ImageUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/image/ImageUtil.java index f99a17e6f..c7c8edda3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/image/ImageUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/image/ImageUtil.java @@ -176,8 +176,8 @@ public class ImageUtil { } public static BufferedImage load(URI uri) throws InputParseException { - try { - return MainUtil.readImage(getInputStream(uri)); + try (final InputStream stream = getInputStream(uri)) { + return MainUtil.readImage(stream); } catch (IOException e) { throw new InputParseException(TextComponent.of(e.getMessage())); } @@ -190,7 +190,7 @@ public class ImageUtil { File file = new File(uri.getPath()); return new FileInputStream(file); } - return new URL(uriStr).openStream(); + return MainUtil.readImageStream(uri); } catch (IOException e) { throw new InputParseException(TextComponent.of(e.getMessage())); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java index 589b5b863..2c8353ce8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java @@ -2,19 +2,22 @@ package com.fastasyncworldedit.core.util.task; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.atomic.AtomicInteger; public class FaweForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory { private final String nameFormat; + private final AtomicInteger idCounter; public FaweForkJoinWorkerThreadFactory(String nameFormat) { this.nameFormat = nameFormat; + this.idCounter = new AtomicInteger(0); } @Override public ForkJoinWorkerThread newThread(ForkJoinPool pool) { final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName(String.format(nameFormat, worker.getPoolIndex())); + worker.setName(String.format(nameFormat, idCounter.getAndIncrement())); return worker; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/UUIDKeyQueuedThreadFactory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/UUIDKeyQueuedThreadFactory.java new file mode 100644 index 000000000..2e87b8c25 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/UUIDKeyQueuedThreadFactory.java @@ -0,0 +1,41 @@ +package com.fastasyncworldedit.core.util.task; + +import org.jetbrains.annotations.ApiStatus; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +@ApiStatus.Internal +public class UUIDKeyQueuedThreadFactory implements ThreadFactory { + + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public UUIDKeyQueuedThreadFactory() { + group = new ThreadGroup("UUIDKeyQueuedThreadGroup"); + namePrefix = "FAWE UUID-key-queued - "; + } + + public Thread newThread(@Nonnull Runnable r) { + Thread t = new UUIDKeyQueuedThread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); + if (t.isDaemon()) { + t.setDaemon(false); + } + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + } + + public static final class UUIDKeyQueuedThread extends Thread { + + public UUIDKeyQueuedThread(@Nullable ThreadGroup group, Runnable task, @Nonnull String name, long stackSize) { + super(group, task, name, stackSize); + } + + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/SimpleWorld.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/SimpleWorld.java index dcc65ae21..1619f114f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/SimpleWorld.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/SimpleWorld.java @@ -58,12 +58,12 @@ public interface SimpleWorld extends World { @Override default int getMaxY() { - return getMaximumPoint().getBlockY(); + return getMaximumPoint().y(); } @Override default int getMinY() { - return getMinimumPoint().getBlockY(); + return getMinimumPoint().y(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java index 4310d6523..37c63a042 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java @@ -1,5 +1,7 @@ package com.fastasyncworldedit.core.world.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -11,9 +13,20 @@ public enum CompoundInput { public BaseBlock get(BlockState state, ITileInput input, int x, int y, int z) { return state.toBaseBlock(input.getTile(x, y, z)); } + + @Override + public BaseBlock get(final BlockState state, final IBlocks blocks, final int x, final int y, final int z) { + final FaweCompoundTag tile = blocks.tile(x, y, z); + return state.toBaseBlock(tile == null ? null : tile.linTag()); + } }; + @Deprecated(forRemoval = true, since = "2.11.2") public BaseBlock get(BlockState state, ITileInput input, int x, int y, int z) { return state.toBaseBlock(); } + + public BaseBlock get(BlockState state, IBlocks blocks, int x, int y, int z) { + return state.toBaseBlock(); + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java index 700070611..077e87e8c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java @@ -97,7 +97,7 @@ public class AsyncPlayer extends PlayerProxy { return false; } - while (y <= world.getMaximumPoint().getY()) { + while (y <= world.getMaximumPoint().y()) { // Found a ceiling! if (world.getBlock(mutable.mutY(y)).getBlockType().getMaterial() .isMovementBlocker()) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java index 05616a414..616e90b37 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.wrappers; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.ExtentTraverser; @@ -187,8 +188,8 @@ public class WorldWrapper extends AbstractWorld { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return parent.setTile(x, y, z, tile); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return parent.tile(x, y, z, tile); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java b/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java deleted file mode 100644 index 1e9d36178..000000000 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/AdventureNBTConverter.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.jnbt; - -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableBiMap; -import com.google.common.collect.ImmutableMap; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagType; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; - -/** - * Converts between JNBT and Adventure-NBT classes. - * - * @deprecated JNBT is being removed in WE8. - */ -@Deprecated(forRemoval = true) -public class AdventureNBTConverter { - - private static final BiMap, BinaryTagType> TAG_TYPES = - new ImmutableBiMap.Builder, BinaryTagType>() - .put(ByteArrayTag.class, BinaryTagTypes.BYTE_ARRAY) - .put(ByteTag.class, BinaryTagTypes.BYTE) - .put(CompoundTag.class, BinaryTagTypes.COMPOUND) - .put(DoubleTag.class, BinaryTagTypes.DOUBLE) - .put(EndTag.class, BinaryTagTypes.END) - .put(FloatTag.class, BinaryTagTypes.FLOAT) - .put(IntArrayTag.class, BinaryTagTypes.INT_ARRAY) - .put(IntTag.class, BinaryTagTypes.INT) - .put(ListTag.class, BinaryTagTypes.LIST) - .put(LongArrayTag.class, BinaryTagTypes.LONG_ARRAY) - .put(LongTag.class, BinaryTagTypes.LONG) - .put(ShortTag.class, BinaryTagTypes.SHORT) - .put(StringTag.class, BinaryTagTypes.STRING) - .build(); - - private static final Map, Function> CONVERSION; - - static { - ImmutableMap.Builder, Function> conversion = - ImmutableMap.builder(); - - for (Map.Entry, BinaryTagType> tag : TAG_TYPES.entrySet()) { - Constructor[] constructors = tag.getKey().getConstructors(); - for (Constructor c : constructors) { - if (c.getParameterCount() == 1 && BinaryTag.class.isAssignableFrom(c.getParameterTypes()[0])) { - conversion.put(tag.getValue(), binaryTag -> { - try { - return (Tag) c.newInstance(binaryTag); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalStateException(e); - } catch (InvocationTargetException e) { - // I assume this is always a RuntimeException since we control the ctor - throw (RuntimeException) e.getCause(); - } - }); - break; - } - } - } - - CONVERSION = conversion.build(); - } - - public static BinaryTagType getAdventureType(Class type) { - return Objects.requireNonNull(TAG_TYPES.get(type), () -> "Missing entry for " + type); - } - - public static Class getJNBTType(BinaryTagType type) { - return Objects.requireNonNull(TAG_TYPES.inverse().get(type), () -> "Missing entry for " + type); - } - - private AdventureNBTConverter() { - } - - public static Tag fromAdventure(BinaryTag other) { - if (other == null) { - return null; - } - Function conversion = CONVERSION.get(other.type()); - if (conversion == null) { - throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); - } - return conversion.apply(other); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java index 094a7c9bb..4889235eb 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteArrayTag.java @@ -19,41 +19,26 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; +import org.enginehub.linbus.tree.LinByteArrayTag; /** * The {@code TAG_Byte_Array} tag. * - * @deprecated Use {@link ByteArrayBinaryTag}. + * @deprecated Use {@link LinByteArrayTag}. */ @Deprecated -public final class ByteArrayTag extends Tag { - - private final ByteArrayBinaryTag innerTag; - +public final class ByteArrayTag extends Tag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public ByteArrayTag(byte[] value) { - super(); - this.innerTag = ByteArrayBinaryTag.of(value); + this(LinByteArrayTag.of(value)); } - public ByteArrayTag(ByteArrayBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public byte[] getValue() { - return innerTag.value(); - } - - @Override - public ByteArrayBinaryTag asBinaryTag() { - return innerTag; + public ByteArrayTag(LinByteArrayTag tag) { + super(tag); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java index 6068b2af0..6b3d3d153 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ByteTag.java @@ -19,41 +19,32 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.ByteBinaryTag; +import com.fastasyncworldedit.core.jnbt.NumberTag; +import org.enginehub.linbus.tree.LinByteTag; /** * The {@code TAG_Byte} tag. * - * @deprecated Use {@link ByteBinaryTag}. + * @deprecated Use {@link LinByteTag}. */ @Deprecated -public final class ByteTag extends Tag { - - private final ByteBinaryTag innerTag; - +public final class ByteTag extends NumberTag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public ByteTag(byte value) { - super(); - this.innerTag = ByteBinaryTag.of(value); + this(LinByteTag.of(value)); } - public ByteTag(ByteBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; + public ByteTag(LinByteTag tag) { + super(tag); } @Override public Byte getValue() { - return innerTag.value(); - } - - @Override - public ByteBinaryTag asBinaryTag() { - return innerTag; + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java index d91aea8fe..10e9adf08 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java @@ -25,10 +25,11 @@ import com.google.common.collect.Maps; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagLike; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.NumberBinaryTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinNumberTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import java.util.Collections; import java.util.HashMap; @@ -39,26 +40,24 @@ import java.util.UUID; /** * The {@code TAG_Compound} tag. * - * @deprecated Use {@link com.sk89q.worldedit.util.nbt.CompoundBinaryTag}. + * @deprecated Use {@link LinCompoundTag}. */ @Deprecated -public class CompoundTag extends Tag { - - private final CompoundBinaryTag innerTag; +//FAWE start - nonfinal +public class CompoundTag extends Tag { + //FAWE end /** * Creates the tag with an empty name. * * @param value the value of the tag */ - public CompoundTag(Map value) { - this(CompoundBinaryTag.builder() - .put(Maps.transformValues(value, BinaryTagLike::asBinaryTag)) - .build()); + public CompoundTag(Map> value) { + this(LinCompoundTag.of(Maps.transformValues(value, Tag::toLinTag))); } - public CompoundTag(CompoundBinaryTag adventureTag) { - this.innerTag = adventureTag; + public CompoundTag(LinCompoundTag tag) { + super(tag); } /** @@ -68,16 +67,16 @@ public class CompoundTag extends Tag { * @return true if the tag contains the given key */ public boolean containsKey(String key) { - return innerTag.keySet().contains(key); + return linTag.value().containsKey(key); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override - public Map getValue() { - ImmutableMap.Builder map = ImmutableMap.builder(); - for (String key : innerTag.keySet()) { - map.put(key, AdventureNBTConverter.fromAdventure(innerTag.get(key))); - } - return map.build(); + public Map> getValue() { + return ImmutableMap.copyOf(Maps.transformValues( + linTag.value(), + tag -> (Tag) LinBusConverter.toJnbtTag((LinTag) tag) + )); } /** @@ -86,7 +85,7 @@ public class CompoundTag extends Tag { * @param value the value * @return the new compound tag */ - public CompoundTag setValue(Map value) { + public CompoundTag setValue(Map> value) { return new CompoundTag(value); } @@ -96,7 +95,7 @@ public class CompoundTag extends Tag { * @return the builder */ public CompoundTagBuilder createBuilder() { - return new CompoundTagBuilder(innerTag); + return new CompoundTagBuilder(linTag); } /** @@ -109,7 +108,8 @@ public class CompoundTag extends Tag { * @return a byte array */ public byte[] getByteArray(String key) { - return this.innerTag.getByteArray(key); + var tag = linTag.findTag(key, LinTagType.byteArrayTag()); + return tag == null ? new byte[0] : tag.value(); } /** @@ -122,7 +122,8 @@ public class CompoundTag extends Tag { * @return a byte */ public byte getByte(String key) { - return this.innerTag.getByte(key); + var tag = linTag.findTag(key, LinTagType.byteTag()); + return tag == null ? 0 : tag.value(); } /** @@ -135,7 +136,8 @@ public class CompoundTag extends Tag { * @return a double */ public double getDouble(String key) { - return this.innerTag.getDouble(key); + var tag = linTag.findTag(key, LinTagType.doubleTag()); + return tag == null ? 0 : tag.value(); } /** @@ -149,9 +151,10 @@ public class CompoundTag extends Tag { * @return a double */ public double asDouble(String key) { - BinaryTag tag = this.innerTag.get(key); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).doubleValue(); + var tag = linTag.value().get(key); + if (tag instanceof LinNumberTag numberTag) { + Number value = numberTag.value(); + return value.doubleValue(); } return 0; } @@ -166,7 +169,8 @@ public class CompoundTag extends Tag { * @return a float */ public float getFloat(String key) { - return this.innerTag.getFloat(key); + var tag = linTag.findTag(key, LinTagType.floatTag()); + return tag == null ? 0 : tag.value(); } /** @@ -179,7 +183,8 @@ public class CompoundTag extends Tag { * @return an int array */ public int[] getIntArray(String key) { - return this.innerTag.getIntArray(key); + var tag = linTag.findTag(key, LinTagType.intArrayTag()); + return tag == null ? new int[0] : tag.value(); } /** @@ -192,7 +197,8 @@ public class CompoundTag extends Tag { * @return an int */ public int getInt(String key) { - return this.innerTag.getInt(key); + var tag = linTag.findTag(key, LinTagType.intTag()); + return tag == null ? 0 : tag.value(); } /** @@ -206,9 +212,10 @@ public class CompoundTag extends Tag { * @return an int */ public int asInt(String key) { - BinaryTag tag = this.innerTag.get(key); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).intValue(); + var tag = linTag.value().get(key); + if (tag instanceof LinNumberTag numberTag) { + Number value = numberTag.value(); + return value.intValue(); } return 0; } @@ -222,7 +229,7 @@ public class CompoundTag extends Tag { * @param key the key * @return a list of tags */ - public List getList(String key) { + public List> getList(String key) { return getListTag(key).getValue(); } @@ -235,8 +242,15 @@ public class CompoundTag extends Tag { * @param key the key * @return a tag list instance */ - public ListTag getListTag(String key) { - return new ListTag(this.innerTag.getList(key)); + public > ListTag getListTag(String key) { + LinListTag tag = linTag.findTag(key, LinTagType.listTag()); + if (tag == null) { + // This is actually hella unsafe. But eh. + @SuppressWarnings("unchecked") + LinTagType endGenerically = (LinTagType) LinTagType.endTag(); + return new ListTag<>(LinListTag.empty(endGenerically)); + } + return new ListTag<>(tag); } /** @@ -253,8 +267,8 @@ public class CompoundTag extends Tag { * @return a list of tags */ @SuppressWarnings("unchecked") - public List getList(String key, Class listType) { - ListTag listTag = getListTag(key); + public > List getList(String key, Class listType) { + ListTag listTag = getListTag(key); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); } else { @@ -272,7 +286,8 @@ public class CompoundTag extends Tag { * @return an int array */ public long[] getLongArray(String key) { - return this.innerTag.getLongArray(key); + var tag = linTag.findTag(key, LinTagType.longArrayTag()); + return tag == null ? new long[0] : tag.value(); } /** @@ -285,7 +300,8 @@ public class CompoundTag extends Tag { * @return a long */ public long getLong(String key) { - return this.innerTag.getLong(key); + var tag = linTag.findTag(key, LinTagType.longTag()); + return tag == null ? 0 : tag.value(); } /** @@ -299,9 +315,10 @@ public class CompoundTag extends Tag { * @return a long */ public long asLong(String key) { - BinaryTag tag = this.innerTag.get(key); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).longValue(); + var tag = linTag.value().get(key); + if (tag instanceof LinNumberTag numberTag) { + Number value = numberTag.value(); + return value.longValue(); } return 0; } @@ -316,7 +333,8 @@ public class CompoundTag extends Tag { * @return a short */ public short getShort(String key) { - return this.innerTag.getShort(key); + var tag = linTag.findTag(key, LinTagType.shortTag()); + return tag == null ? 0 : tag.value(); } /** @@ -329,12 +347,8 @@ public class CompoundTag extends Tag { * @return a string */ public String getString(String key) { - return this.innerTag.getString(key); - } - - @Override - public CompoundBinaryTag asBinaryTag() { - return this.innerTag; + var tag = linTag.findTag(key, LinTagType.stringTag()); + return tag == null ? "" : tag.value(); } @@ -357,7 +371,7 @@ public class CompoundTag extends Tag { } public Vector3 getEntityPosition() { - List posTags = getList("Pos"); + List> posTags = getList("Pos"); double x = ((NumberTag) posTags.get(0)).getValue().doubleValue(); double y = ((NumberTag) posTags.get(1)).getValue().doubleValue(); double z = ((NumberTag) posTags.get(2)).getValue().doubleValue(); @@ -365,7 +379,7 @@ public class CompoundTag extends Tag { } public Location getEntityLocation(Extent extent) { - List rotTag = getList("Rotation"); + List> rotTag = getList("Rotation"); float yaw = ((NumberTag) rotTag.get(0)).getValue().floatValue(); float pitch = ((NumberTag) rotTag.get(1)).getValue().floatValue(); return new Location(extent, getEntityPosition(), yaw, pitch); @@ -382,7 +396,7 @@ public class CompoundTag extends Tag { if (this.getValue().isEmpty()) { return raw; } - for (Map.Entry entry : getValue().entrySet()) { + for (Map.Entry> entry : getValue().entrySet()) { raw.put(entry.getKey(), entry.getValue().toRaw()); } return raw; diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java index f21bdb8cc..535722b74 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTagBuilder.java @@ -19,27 +19,27 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.Map; -import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; /** * Helps create compound tags. * - * @deprecated Use {@link com.sk89q.worldedit.util.nbt.CompoundBinaryTag.Builder}. + * @deprecated Use {@link LinCompoundTag.Builder}. */ @Deprecated public class CompoundTagBuilder { - private final CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder(); + private final LinCompoundTag.Builder builder; /** * Create a new instance. */ CompoundTagBuilder() { + this.builder = LinCompoundTag.builder(); } /** @@ -47,11 +47,9 @@ public class CompoundTagBuilder { * * @param source the value */ - CompoundTagBuilder(CompoundBinaryTag source) { + CompoundTagBuilder(LinCompoundTag source) { checkNotNull(source); - for (String key : source.keySet()) { - this.builder.put(key, Objects.requireNonNull(source.get(key))); - } + this.builder = source.toBuilder(); } /** @@ -61,10 +59,10 @@ public class CompoundTagBuilder { * @param value the value * @return this object */ - public CompoundTagBuilder put(String key, Tag value) { + public CompoundTagBuilder put(String key, Tag value) { checkNotNull(key); checkNotNull(value); - this.builder.put(key, value.asBinaryTag()); + this.builder.put(key, value.toLinTag()); return this; } @@ -215,9 +213,9 @@ public class CompoundTagBuilder { * @param value the map of tags * @return this object */ - public CompoundTagBuilder putAll(Map value) { + public CompoundTagBuilder putAll(Map> value) { checkNotNull(value); - for (Map.Entry entry : value.entrySet()) { + for (Map.Entry> entry : value.entrySet()) { put(entry.getKey(), entry.getValue()); } return this; diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java index da0890ea6..6dad5186b 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/DoubleTag.java @@ -20,17 +20,15 @@ package com.sk89q.jnbt; import com.fastasyncworldedit.core.jnbt.NumberTag; -import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; +import org.enginehub.linbus.tree.LinDoubleTag; /** * The {@code TAG_Double} tag. * - * @deprecated Use {@link DoubleBinaryTag}. + * @deprecated Use {@link LinDoubleTag}. */ @Deprecated -public final class DoubleTag extends NumberTag { - - private final DoubleBinaryTag innerTag; +public final class DoubleTag extends NumberTag { /** * Creates the tag with an empty name. @@ -38,23 +36,16 @@ public final class DoubleTag extends NumberTag { * @param value the value of the tag */ public DoubleTag(double value) { - super(); - this.innerTag = DoubleBinaryTag.of(value); + this(LinDoubleTag.of(value)); } - public DoubleTag(DoubleBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public DoubleBinaryTag asBinaryTag() { - return this.innerTag; + public DoubleTag(LinDoubleTag tag) { + super(tag); } @Override public Double getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java index 18347d928..523fcf79e 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/EndTag.java @@ -19,24 +19,17 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.EndBinaryTag; +import org.enginehub.linbus.tree.LinEndTag; /** * The {@code TAG_End} tag. * - * @deprecated Use {@link com.sk89q.worldedit.util.nbt.EndBinaryTag}. + * @deprecated Use {@link LinEndTag}. */ @Deprecated -public final class EndTag extends Tag { - - @Override - public Object getValue() { - return null; - } - - @Override - public EndBinaryTag asBinaryTag() { - return EndBinaryTag.get(); +public final class EndTag extends Tag { + public EndTag() { + super(LinEndTag.instance()); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java index 2e1533827..128e36014 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/FloatTag.java @@ -20,17 +20,14 @@ package com.sk89q.jnbt; import com.fastasyncworldedit.core.jnbt.NumberTag; -import com.sk89q.worldedit.util.nbt.FloatBinaryTag; +import org.enginehub.linbus.tree.LinFloatTag; /** * The {@code TAG_Float} tag. * - * @deprecated Use {@link FloatBinaryTag}. + * @deprecated Use {@link LinFloatTag}. */ -@Deprecated -public final class FloatTag extends NumberTag { - - private final FloatBinaryTag innerTag; +public final class FloatTag extends NumberTag { /** * Creates the tag with an empty name. @@ -38,23 +35,16 @@ public final class FloatTag extends NumberTag { * @param value the value of the tag */ public FloatTag(float value) { - super(); - this.innerTag = FloatBinaryTag.of(value); + this(LinFloatTag.of(value)); } - public FloatTag(FloatBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public FloatBinaryTag asBinaryTag() { - return this.innerTag; + public FloatTag(LinFloatTag tag) { + super(tag); } @Override public Float getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java index 76d8fac74..0e3536eed 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/IntArrayTag.java @@ -19,44 +19,33 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; +import org.enginehub.linbus.tree.LinIntArrayTag; import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_Int_Array} tag. * - * @deprecated Use {@link IntArrayBinaryTag}. + * @deprecated Use {@link LinIntArrayTag}. */ @Deprecated -public final class IntArrayTag extends Tag { - - private final IntArrayBinaryTag innerTag; - +public final class IntArrayTag extends Tag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public IntArrayTag(int[] value) { - super(); - checkNotNull(value); - this.innerTag = IntArrayBinaryTag.of(value); + this(LinIntArrayTag.of(checkNotNull(value))); } - public IntArrayTag(IntArrayBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public IntArrayBinaryTag asBinaryTag() { - return this.innerTag; + public IntArrayTag(LinIntArrayTag tag) { + super(tag); } @Override public int[] getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java index c6ff80252..c4c90889b 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/IntTag.java @@ -19,17 +19,16 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.fastasyncworldedit.core.jnbt.NumberTag; +import org.enginehub.linbus.tree.LinIntTag; /** * The {@code TAG_Int} tag. * - * @deprecated Use {@link IntBinaryTag}. + * @deprecated Use {@link LinIntTag}. */ @Deprecated -public final class IntTag extends Tag { - - private final IntBinaryTag innerTag; +public final class IntTag extends NumberTag { /** * Creates the tag with an empty name. @@ -37,23 +36,16 @@ public final class IntTag extends Tag { * @param value the value of the tag */ public IntTag(int value) { - super(); - this.innerTag = IntBinaryTag.of(value); + this(LinIntTag.of(value)); } - public IntTag(IntBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public IntBinaryTag asBinaryTag() { - return this.innerTag; + public IntTag(LinIntTag tag) { + super(tag); } @Override public Integer getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LazyCompoundTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LazyCompoundTag.java index 00b5aeb9a..4ce6febd6 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/LazyCompoundTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LazyCompoundTag.java @@ -20,27 +20,27 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.Map; /** * Allows detection of the version-specific LazyCompoundTag classes. * - * @deprecated Use {@link CompoundBinaryTag}. + * @deprecated Use {@link LinCompoundTag}. */ @Deprecated public abstract class LazyCompoundTag extends CompoundTag { - public LazyCompoundTag(Map value) { + public LazyCompoundTag(Map> value) { super(value); } - public LazyCompoundTag(CompoundBinaryTag adventureTag) { + public LazyCompoundTag(LinCompoundTag adventureTag) { super(adventureTag); } @Override - public abstract CompoundBinaryTag asBinaryTag(); + public abstract LinCompoundTag toLinTag(); } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LinBusConverter.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LinBusConverter.java new file mode 100644 index 000000000..52b30f599 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LinBusConverter.java @@ -0,0 +1,140 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.jnbt; + +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableMap; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongArrayTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; + +/** + * Converts between JNBT and Adventure-NBT classes. + * + * @deprecated JNBT is being removed in WE8. + */ +@Deprecated(forRemoval = true) +public class LinBusConverter { + + private static final BiMap, LinTagType> TAG_TYPES = + new ImmutableBiMap.Builder, LinTagType>() + .put(ByteArrayTag.class, LinTagType.byteArrayTag()) + .put(ByteTag.class, LinTagType.byteTag()) + .put(CompoundTag.class, LinTagType.compoundTag()) + .put(DoubleTag.class, LinTagType.doubleTag()) + .put(EndTag.class, LinTagType.endTag()) + .put(FloatTag.class, LinTagType.floatTag()) + .put(IntArrayTag.class, LinTagType.intArrayTag()) + .put(IntTag.class, LinTagType.intTag()) + .put(ListTag.class, LinTagType.listTag()) + .put(LongArrayTag.class, LinTagType.longArrayTag()) + .put(LongTag.class, LinTagType.longTag()) + .put(ShortTag.class, LinTagType.shortTag()) + .put(StringTag.class, LinTagType.stringTag()) + .build(); + + private static final Map, Function> CONVERSION; + + static { + ImmutableMap.Builder, Function> conversion = + ImmutableMap.builder(); + + for (Map.Entry, LinTagType> tag : TAG_TYPES.entrySet()) { + Constructor[] constructors = tag.getKey().getConstructors(); + for (Constructor c : constructors) { + if (c.getParameterCount() == 1 && LinTag.class.isAssignableFrom(c.getParameterTypes()[0])) { + conversion.put(tag.getValue(), linTag -> { + try { + return (Tag) c.newInstance(linTag); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + // I assume this is always a RuntimeException since we control the ctor + throw (RuntimeException) e.getCause(); + } + }); + break; + } + } + } + + CONVERSION = conversion.build(); + } + + public static LinTagType getAdventureType(Class type) { + return Objects.requireNonNull(TAG_TYPES.get(type), () -> "Missing entry for " + type); + } + + public static Class getJNBTType(LinTagType type) { + return Objects.requireNonNull(TAG_TYPES.inverse().get(type), () -> "Missing entry for " + type); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static > Tag toJnbtTag(LT tag) { + return (Tag) switch (tag.type().id()) { + case BYTE_ARRAY -> new ByteArrayTag((LinByteArrayTag) tag); + case BYTE -> new ByteTag((LinByteTag) tag); + case COMPOUND -> new CompoundTag((LinCompoundTag) tag); + case DOUBLE -> new DoubleTag((LinDoubleTag) tag); + case END -> new EndTag(); + case FLOAT -> new FloatTag((LinFloatTag) tag); + case INT_ARRAY -> new IntArrayTag((LinIntArrayTag) tag); + case INT -> new IntTag((LinIntTag) tag); + case LIST -> new ListTag((LinListTag) tag); + case LONG_ARRAY -> new LongArrayTag((LinLongArrayTag) tag); + case LONG -> new LongTag((LinLongTag) tag); + case SHORT -> new ShortTag((LinShortTag) tag); + case STRING -> new StringTag((LinStringTag) tag); + }; + } + + private LinBusConverter() { + } + + public static Tag fromLinBus(LinTag other) { + if (other == null) { + return null; + } + Function conversion = CONVERSION.get(other.type()); + if (conversion == null) { + throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); + } + return conversion.apply(other); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java index 879a0d4a3..d3c330d4d 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java @@ -19,10 +19,20 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagLike; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; -import com.sk89q.worldedit.util.nbt.NumberBinaryTag; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinByteTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongTag; +import org.enginehub.linbus.tree.LinNumberTag; +import org.enginehub.linbus.tree.LinShortTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nullable; import java.util.Collections; @@ -34,12 +44,10 @@ import java.util.stream.Collectors; /** * The {@code TAG_List} tag. * - * @deprecated Use {@link com.sk89q.worldedit.util.nbt.ListBinaryTag}. + * @deprecated Use {@link LinListTag}. */ @Deprecated -public final class ListTag extends Tag { - - private final ListBinaryTag innerTag; +public final class ListTag> extends Tag> { /** * Creates the tag with an empty name. @@ -47,20 +55,15 @@ public final class ListTag extends Tag { * @param type the type of tag * @param value the value of the tag */ - public ListTag(Class type, List value) { - this(ListBinaryTag.of( - AdventureNBTConverter.getAdventureType(type), - value.stream().map(BinaryTagLike::asBinaryTag).collect(Collectors.toList()) + public ListTag(Class> type, List> value) { + this(LinListTag.of( + LinTagType.fromId(LinTagId.fromId(NBTUtils.getTypeCode(type))), + value.stream().map(Tag::toLinTag).collect(Collectors.toList()) )); } - public ListTag(ListBinaryTag adventureTag) { - this.innerTag = adventureTag; - } - - @Override - public ListBinaryTag asBinaryTag() { - return this.innerTag; + public ListTag(LinListTag tag) { + super(tag); } /** @@ -68,15 +71,14 @@ public final class ListTag extends Tag { * * @return The type of item in this list. */ - public Class getType() { - return AdventureNBTConverter.getJNBTType(this.innerTag.elementType()); + @SuppressWarnings("unchecked") + public Class> getType() { + return (Class>) NBTUtils.getTypeClass(linTag.elementType().id().id()); } @Override - public List getValue() { - return this.innerTag.stream() - .map(AdventureNBTConverter::fromAdventure) - .collect(Collectors.toList()); + public List> getValue() { + return linTag.value().stream().map(LinBusConverter::toJnbtTag).toList(); } /** @@ -85,17 +87,31 @@ public final class ListTag extends Tag { * @param list the new list * @return a new list tag */ - public ListTag setValue(List list) { - return new ListTag(getType(), list); + public ListTag setValue(List> list) { + return new ListTag<>(getType(), list); } private T accessIfExists(int index, Supplier defaultValue, IntFunction accessor) { - if (index >= this.innerTag.size()) { + if (index >= this.linTag.value().size()) { return defaultValue.get(); } return accessor.apply(index); } + @SuppressWarnings("unchecked") + private > T extractViaValue( + int index, Class requiredType, Supplier defaultValue + ) { + if (index >= this.linTag.value().size()) { + return defaultValue.get(); + } + E value = this.linTag.get(index); + if (!requiredType.isInstance(value)) { + return defaultValue.get(); + } + return (T) value.value(); + } + /** * Get the tag if it exists at the given index. * @@ -103,11 +119,11 @@ public final class ListTag extends Tag { * @return the tag or null */ @Nullable - public Tag getIfExists(int index) { + public Tag getIfExists(int index) { return accessIfExists( - index, - () -> null, - i -> AdventureNBTConverter.fromAdventure(this.innerTag.get(i)) + index, + () -> null, + i -> LinBusConverter.toJnbtTag(this.linTag.get(i)) ); } @@ -121,11 +137,7 @@ public final class ListTag extends Tag { * @return a byte array */ public byte[] getByteArray(int index) { - return accessIfExists( - index, - () -> new byte[0], - this.innerTag::getByteArray - ); + return extractViaValue(index, LinByteArrayTag.class, () -> new byte[0]); } /** @@ -138,11 +150,7 @@ public final class ListTag extends Tag { * @return a byte */ public byte getByte(int index) { - return accessIfExists( - index, - () -> (byte) 0, - this.innerTag::getByte - ); + return extractViaValue(index, LinByteTag.class, () -> (byte) 0); } /** @@ -155,11 +163,7 @@ public final class ListTag extends Tag { * @return a double */ public double getDouble(int index) { - return accessIfExists( - index, - () -> 0.0, - this.innerTag::getDouble - ); + return extractViaValue(index, LinDoubleTag.class, () -> 0.0); } /** @@ -174,15 +178,11 @@ public final class ListTag extends Tag { */ public double asDouble(int index) { return accessIfExists( - index, - () -> 0.0, - i -> { - BinaryTag tag = this.innerTag.get(i); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).doubleValue(); - } - return 0.0; - } + index, + () -> 0.0, + i -> this.linTag.get(i) instanceof LinNumberTag tag + ? tag.value().doubleValue() + : 0.0 ); } @@ -196,11 +196,7 @@ public final class ListTag extends Tag { * @return a float */ public float getFloat(int index) { - return accessIfExists( - index, - () -> 0.0f, - this.innerTag::getFloat - ); + return extractViaValue(index, LinFloatTag.class, () -> 0f); } /** @@ -213,11 +209,7 @@ public final class ListTag extends Tag { * @return an int array */ public int[] getIntArray(int index) { - return accessIfExists( - index, - () -> new int[0], - this.innerTag::getIntArray - ); + return extractViaValue(index, LinIntArrayTag.class, () -> new int[0]); } /** @@ -230,11 +222,7 @@ public final class ListTag extends Tag { * @return an int */ public int getInt(int index) { - return accessIfExists( - index, - () -> 0, - this.innerTag::getInt - ); + return extractViaValue(index, LinIntTag.class, () -> 0); } /** @@ -249,15 +237,11 @@ public final class ListTag extends Tag { */ public int asInt(int index) { return accessIfExists( - index, - () -> 0, - i -> { - BinaryTag tag = this.innerTag.get(i); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).intValue(); - } - return 0; - } + index, + () -> 0, + i -> this.linTag.get(i) instanceof LinNumberTag tag + ? tag.value().intValue() + : 0 ); } @@ -270,7 +254,7 @@ public final class ListTag extends Tag { * @param index the index * @return a list of tags */ - public List getList(int index) { + public List> getList(int index) { return getListTag(index).getValue(); } @@ -283,11 +267,12 @@ public final class ListTag extends Tag { * @param index the index * @return a tag list instance */ - public ListTag getListTag(int index) { - return new ListTag(accessIfExists( - index, - ListBinaryTag::empty, - this.innerTag::getList + @SuppressWarnings("unchecked") + public ListTag getListTag(int index) { + return new ListTag<>(extractViaValue( + index, + LinListTag.class, + () -> LinListTag.empty(LinTagType.endTag()) )); } @@ -305,8 +290,8 @@ public final class ListTag extends Tag { * @return a list of tags */ @SuppressWarnings("unchecked") - public List getList(int index, Class listType) { - ListTag listTag = getListTag(index); + public > List getList(int index, Class listType) { + ListTag listTag = getListTag(index); if (listTag.getType().equals(listType)) { return (List) listTag.getValue(); } else { @@ -324,11 +309,7 @@ public final class ListTag extends Tag { * @return a long */ public long getLong(int index) { - return accessIfExists( - index, - () -> 0L, - this.innerTag::getLong - ); + return extractViaValue(index, LinLongTag.class, () -> 0L); } /** @@ -343,15 +324,11 @@ public final class ListTag extends Tag { */ public long asLong(int index) { return accessIfExists( - index, - () -> 0L, - i -> { - BinaryTag tag = this.innerTag.get(i); - if (tag instanceof NumberBinaryTag) { - return ((NumberBinaryTag) tag).longValue(); - } - return 0L; - } + index, + () -> 0L, + i -> this.linTag.get(i) instanceof LinNumberTag tag + ? tag.value().longValue() + : 0L ); } @@ -365,11 +342,7 @@ public final class ListTag extends Tag { * @return a short */ public short getShort(int index) { - return accessIfExists( - index, - () -> (short) 0, - this.innerTag::getShort - ); + return extractViaValue(index, LinShortTag.class, () -> (short) 0); } /** @@ -382,11 +355,7 @@ public final class ListTag extends Tag { * @return a string */ public String getString(int index) { - return accessIfExists( - index, - () -> "", - this.innerTag::getString - ); + return extractViaValue(index, LinStringTag.class, () -> ""); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java index 78a8b6401..18aab079c 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTagBuilder.java @@ -19,11 +19,11 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagType; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import org.enginehub.linbus.common.LinTagId; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; -import java.util.Arrays; import java.util.Collection; import static com.google.common.base.Preconditions.checkNotNull; @@ -31,12 +31,12 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Helps create list tags. * - * @deprecated Use {@link com.sk89q.worldedit.util.nbt.ListBinaryTag.Builder}. + * @deprecated Use {@link LinListTag.Builder}. */ @Deprecated -public class ListTagBuilder { +public class ListTagBuilder> { - private final ListBinaryTag.Builder builder; + private final LinListTag.Builder builder; /** * Create a new instance. @@ -44,11 +44,11 @@ public class ListTagBuilder { * @param type of tag contained in this list */ @SuppressWarnings("unchecked") - ListTagBuilder(Class type) { + ListTagBuilder(Class> type) { checkNotNull(type); - this.builder = type != EndTag.class - ? ListBinaryTag.builder((BinaryTagType) AdventureNBTConverter.getAdventureType(type)) - : ListBinaryTag.builder(); + this.builder = (LinListTag.Builder) LinListTag.builder(LinTagType.fromId(LinTagId.fromId( + NBTUtils.getTypeCode(type) + ))); } /** @@ -57,9 +57,9 @@ public class ListTagBuilder { * @param value the tag * @return this object */ - public ListTagBuilder add(Tag value) { + public ListTagBuilder add(Tag value) { checkNotNull(value); - builder.add(value.asBinaryTag()); + builder.add(value.toLinTag()); return this; } @@ -69,9 +69,9 @@ public class ListTagBuilder { * @param value a list of tags * @return this object */ - public ListTagBuilder addAll(Collection value) { + public ListTagBuilder addAll(Collection> value) { checkNotNull(value); - for (Tag v : value) { + for (Tag v : value) { add(v); } return this; @@ -82,8 +82,8 @@ public class ListTagBuilder { * * @return the new list tag */ - public ListTag build() { - return new ListTag(this.builder.build()); + public ListTag build() { + return new ListTag<>(this.builder.build()); } /** @@ -91,8 +91,8 @@ public class ListTagBuilder { * * @return a new builder */ - public static ListTagBuilder create(Class type) { - return new ListTagBuilder(type); + public static > ListTagBuilder create(Class> type) { + return new ListTagBuilder<>(type); } /** @@ -100,22 +100,24 @@ public class ListTagBuilder { * * @return a new builder */ - public static ListTagBuilder createWith(Tag... entries) { + @SafeVarargs + public static > ListTagBuilder createWith(Tag... entries) { checkNotNull(entries); if (entries.length == 0) { throw new IllegalArgumentException("This method needs an array of at least one entry"); } - Class type = entries[0].getClass(); - for (int i = 1; i < entries.length; i++) { - if (!type.isInstance(entries[i])) { + @SuppressWarnings("unchecked") + Class> type = (Class>) entries[0].getClass(); + ListTagBuilder builder = new ListTagBuilder<>(type); + for (Tag entry : entries) { + if (!type.isInstance(entry)) { throw new IllegalArgumentException("An array of different tag types was provided"); } + builder.add(entry); } - ListTagBuilder builder = new ListTagBuilder(type); - builder.addAll(Arrays.asList(entries)); return builder; } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java index 81c6e3376..968019b7e 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LongArrayTag.java @@ -19,44 +19,33 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; +import org.enginehub.linbus.tree.LinLongArrayTag; import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_Long_Array} tag. * - * @deprecated Use {@link LongArrayBinaryTag}. + * @deprecated Use {@link LinLongArrayTag}. */ @Deprecated -public class LongArrayTag extends Tag { - - private final LongArrayBinaryTag innerTag; - +public class LongArrayTag extends Tag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public LongArrayTag(long[] value) { - super(); - checkNotNull(value); - this.innerTag = LongArrayBinaryTag.of(value); + this(LinLongArrayTag.of(checkNotNull(value))); } - public LongArrayTag(LongArrayBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public LongArrayBinaryTag asBinaryTag() { - return this.innerTag; + public LongArrayTag(LinLongArrayTag tag) { + super(tag); } @Override public long[] getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java index 84a443746..b8632b752 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/LongTag.java @@ -19,41 +19,32 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.LongBinaryTag; +import com.fastasyncworldedit.core.jnbt.NumberTag; +import org.enginehub.linbus.tree.LinLongTag; /** * The {@code TAG_Long} tag. * - * @deprecated Use {@link LongBinaryTag}. + * @deprecated Use {@link LinLongTag}. */ @Deprecated -public final class LongTag extends Tag { - - private final LongBinaryTag innerTag; - +public final class LongTag extends NumberTag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public LongTag(long value) { - super(); - this.innerTag = LongBinaryTag.of(value); + this(LinLongTag.of(value)); } - public LongTag(LongBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public LongBinaryTag asBinaryTag() { - return this.innerTag; + public LongTag(LinLongTag tag) { + super(tag); } @Override public Long getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java index 54746fc49..3ab1923c1 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTConstants.java @@ -50,7 +50,6 @@ public final class NBTConstants { * Default private constructor. */ private NBTConstants() { - } /** @@ -60,37 +59,27 @@ public final class NBTConstants { * @return tag class * @throws IllegalArgumentException thrown if the tag ID is not valid */ - public static Class getClassFromType(int id) { - switch (id) { - case TYPE_END: - return EndTag.class; - case TYPE_BYTE: - return ByteTag.class; - case TYPE_SHORT: - return ShortTag.class; - case TYPE_INT: - return IntTag.class; - case TYPE_LONG: - return LongTag.class; - case TYPE_FLOAT: - return FloatTag.class; - case TYPE_DOUBLE: - return DoubleTag.class; - case TYPE_BYTE_ARRAY: - return ByteArrayTag.class; - case TYPE_STRING: - return StringTag.class; - case TYPE_LIST: - return ListTag.class; - case TYPE_COMPOUND: - return CompoundTag.class; - case TYPE_INT_ARRAY: - return IntArrayTag.class; - case TYPE_LONG_ARRAY: - return LongArrayTag.class; - default: - throw new IllegalArgumentException("Unknown tag type ID of " + id); - } + public static Class> getClassFromType(int id) { + return switch (id) { + case TYPE_END -> EndTag.class; + case TYPE_BYTE -> ByteTag.class; + case TYPE_SHORT -> ShortTag.class; + case TYPE_INT -> IntTag.class; + case TYPE_LONG -> LongTag.class; + case TYPE_FLOAT -> FloatTag.class; + case TYPE_DOUBLE -> DoubleTag.class; + case TYPE_BYTE_ARRAY -> ByteArrayTag.class; + case TYPE_STRING -> StringTag.class; + case TYPE_LIST -> { + @SuppressWarnings("unchecked") + var aClass = (Class>) (Class) ListTag.class; + yield aClass; + } + case TYPE_COMPOUND -> CompoundTag.class; + case TYPE_INT_ARRAY -> IntArrayTag.class; + case TYPE_LONG_ARRAY -> LongArrayTag.class; + default -> throw new IllegalArgumentException("Unknown tag type ID of " + id); + }; } } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java index fca025212..080ab3bea 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTInputStream.java @@ -21,6 +21,7 @@ package com.sk89q.jnbt; import com.fastasyncworldedit.core.jnbt.streamer.StreamDelegate; import com.fastasyncworldedit.core.jnbt.streamer.ValueReader; +import org.enginehub.linbus.stream.LinBinaryIO; import java.io.Closeable; import java.io.DataInputStream; @@ -44,8 +45,9 @@ import java.util.Map; * https://minecraft.gamepedia.com/NBT_format. *

* - * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. + * @deprecated JNBT is being removed for lin-bus in WorldEdit 8, use {@link LinBinaryIO} instead */ +@SuppressWarnings("removal") @Deprecated(forRemoval = true) public final class NBTInputStream implements Closeable { @@ -77,7 +79,6 @@ public final class NBTInputStream implements Closeable { * Reads an NBT tag from the stream. * * @return The tag that was read. - * @throws IOException if an I/O error occurs. */ public NamedTag readNamedTag() throws IOException { return readNamedTag(0); @@ -571,7 +572,7 @@ public final class NBTInputStream implements Closeable { * @return the tag * @throws IOException if an I/O error occurs. */ - private Tag readTagPayload(int type, int depth) throws IOException { + public Tag readTagPayload(int type, int depth) throws IOException { //FAWE - public switch (type) { case NBTConstants.TYPE_END: if (depth == 0) { @@ -617,7 +618,7 @@ public final class NBTInputStream implements Closeable { return new ListTag(NBTUtils.getTypeClass(childType), tagList); case NBTConstants.TYPE_COMPOUND: - Map tagMap = new HashMap<>(); + Map> tagMap = new HashMap<>(); while (true) { NamedTag namedTag = readNamedTag(depth + 1); Tag tag = namedTag.getTag(); diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java index 6342455eb..b466e6de2 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java @@ -20,6 +20,7 @@ package com.sk89q.jnbt; import com.fastasyncworldedit.core.internal.io.LittleEndianOutputStream; +import org.enginehub.linbus.stream.LinBinaryIO; import java.io.Closeable; import java.io.DataOutput; @@ -44,8 +45,9 @@ import static com.google.common.base.Preconditions.checkNotNull; * https://minecraft.gamepedia.com/NBT_format. *

* - * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. + * @deprecated JNBT is being removed for lin-bus in WorldEdit 8, use {@link LinBinaryIO} instead */ +@SuppressWarnings("removal") @Deprecated(forRemoval = true) public final class NBTOutputStream extends OutputStream implements Closeable, DataOutput { @@ -61,7 +63,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da * @param os The output stream. * @throws IOException if an I/O error occurs. */ - public NBTOutputStream(OutputStream os) throws IOException { + public NBTOutputStream(OutputStream os) { this(os instanceof DataOutput ? (DataOutput) os : new DataOutputStream(os)); } @@ -91,11 +93,11 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da * @param tag The tag to write. * @throws IOException if an I/O error occurs. */ - public void writeNamedTag(String name, Tag tag) throws IOException { + public void writeNamedTag(String name, Tag tag) throws IOException { checkNotNull(name); checkNotNull(tag); - int type = NBTUtils.getTypeCode(tag.getClass()); + int type = tag.getTypeCode(); writeNamedTagName(name, type); if (type == NBTConstants.TYPE_END) { @@ -196,7 +198,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da } public void writeTag(Tag tag) throws IOException { - int type = NBTUtils.getTypeCode(tag.getClass()); + int type = tag.getTypeCode(); os.writeByte(type); writeTagPayload(tag); } @@ -212,7 +214,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da * @throws IOException if an I/O error occurs. */ public void writeTagPayload(Tag tag) throws IOException { - int type = NBTUtils.getTypeCode(tag.getClass()); + int type = tag.getTypeCode(); switch (type) { case NBTConstants.TYPE_END: writeEndTagPayload((EndTag) tag); @@ -287,7 +289,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da * @throws IOException if an I/O error occurs. */ private void writeCompoundTagPayload(CompoundTag tag) throws IOException { - for (Map.Entry entry : tag.getValue().entrySet()) { + for (Map.Entry> entry : tag.getValue().entrySet()) { writeNamedTag(entry.getKey(), entry.getValue()); } os.writeByte((byte) 0); // end tag - better way? @@ -300,7 +302,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da * @throws IOException if an I/O error occurs. */ private void writeListTagPayload(ListTag tag) throws IOException { - Class clazz = tag.getType(); + Class> clazz = tag.getType(); if (clazz == null) { clazz = CompoundTag.class; } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java index c899ba07b..9b28a6d30 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java @@ -20,7 +20,6 @@ package com.sk89q.jnbt; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; import com.sk89q.worldedit.world.storage.InvalidFormatException; import java.util.Map; @@ -33,6 +32,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. */ +@SuppressWarnings("ALL") @Deprecated public final class NBTUtils { @@ -48,7 +48,7 @@ public final class NBTUtils { * @param clazz the tag class * @return The type name. */ - public static String getTypeName(Class clazz) { + public static String getTypeName(Class> clazz) { if (clazz.equals(ByteArrayTag.class)) { return "TAG_Byte_Array"; } else if (clazz.equals(ByteTag.class)) { @@ -77,7 +77,7 @@ public final class NBTUtils { return "TAG_Long_Array"; } else { throw new IllegalArgumentException("Invalid tag class (" - + clazz.getName() + ")."); + + clazz.getName() + ")."); } } @@ -88,11 +88,35 @@ public final class NBTUtils { * @return The type code. * @throws IllegalArgumentException if the tag class is invalid. */ - public static int getTypeCode(Class clazz) { - if (LazyCompoundTag.class.isAssignableFrom(clazz)) { - return BinaryTagTypes.COMPOUND.id(); + public static int getTypeCode(Class> clazz) { + if (clazz == ByteArrayTag.class) { + return NBTConstants.TYPE_BYTE_ARRAY; + } else if (clazz == ByteTag.class) { + return NBTConstants.TYPE_BYTE; + } else if (clazz == CompoundTag.class) { + return NBTConstants.TYPE_COMPOUND; + } else if (clazz == DoubleTag.class) { + return NBTConstants.TYPE_DOUBLE; + } else if (clazz == EndTag.class) { + return NBTConstants.TYPE_END; + } else if (clazz == FloatTag.class) { + return NBTConstants.TYPE_FLOAT; + } else if (clazz == IntArrayTag.class) { + return NBTConstants.TYPE_INT_ARRAY; + } else if (clazz == IntTag.class) { + return NBTConstants.TYPE_INT; + } else if (clazz.equals(ListTag.class) /* I hate this, it wouldn't do == b/c generics */) { + return NBTConstants.TYPE_LIST; + } else if (clazz == LongArrayTag.class) { + return NBTConstants.TYPE_LONG_ARRAY; + } else if (clazz == LongTag.class) { + return NBTConstants.TYPE_LONG; + } else if (clazz == ShortTag.class) { + return NBTConstants.TYPE_SHORT; + } else if (clazz == StringTag.class) { + return NBTConstants.TYPE_STRING; } - return AdventureNBTConverter.getAdventureType(clazz).id(); + throw new IllegalArgumentException("Invalid tag class (" + clazz.getName() + ")"); } /** @@ -102,38 +126,8 @@ public final class NBTUtils { * @return The class. * @throws IllegalArgumentException if the tag type is invalid. */ - public static Class getTypeClass(int type) { - switch (type) { - case NBTConstants.TYPE_END: - return EndTag.class; - case NBTConstants.TYPE_BYTE: - return ByteTag.class; - case NBTConstants.TYPE_SHORT: - return ShortTag.class; - case NBTConstants.TYPE_INT: - return IntTag.class; - case NBTConstants.TYPE_LONG: - return LongTag.class; - case NBTConstants.TYPE_FLOAT: - return FloatTag.class; - case NBTConstants.TYPE_DOUBLE: - return DoubleTag.class; - case NBTConstants.TYPE_BYTE_ARRAY: - return ByteArrayTag.class; - case NBTConstants.TYPE_STRING: - return StringTag.class; - case NBTConstants.TYPE_LIST: - return ListTag.class; - case NBTConstants.TYPE_COMPOUND: - return CompoundTag.class; - case NBTConstants.TYPE_INT_ARRAY: - return IntArrayTag.class; - case NBTConstants.TYPE_LONG_ARRAY: - return LongArrayTag.class; - default: - throw new IllegalArgumentException("Invalid tag type : " + type - + "."); - } + public static Class> getTypeClass(int type) { + return NBTConstants.getClassFromType(type); } /** @@ -145,7 +139,7 @@ public final class NBTUtils { * @param listTag the list tag * @return a vector */ - public static Vector3 toVector(ListTag listTag) { + public static Vector3 toVector(ListTag listTag) { checkNotNull(listTag); return Vector3.at(listTag.asDouble(0), listTag.asDouble(1), listTag.asDouble(2)); } @@ -159,12 +153,12 @@ public final class NBTUtils { * @return child tag * @throws InvalidFormatException if the format of the items is invalid */ - public static T getChildTag(Map items, String key, Class expected) throws + public static > T getChildTag(Map> items, String key, Class expected) throws InvalidFormatException { if (!items.containsKey(key)) { throw new InvalidFormatException("Missing a \"" + key + "\" tag"); } - Tag tag = items.get(key); + Tag tag = items.get(key); if (!expected.isInstance(tag)) { throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName()); } @@ -178,8 +172,10 @@ public final class NBTUtils { * @param map Map to add uuid to * @param uuid {@link UUID} to add * @since 2.4.0 + * @deprecated use {@link com.fastasyncworldedit.core.util.NbtUtils#addUUIDToMap(Map, UUID)} instead */ - public static void addUUIDToMap(Map map, UUID uuid) { + @Deprecated(forRemoval = true, since = "2.11.2") + public static void addUUIDToMap(Map> map, UUID uuid) { int[] uuidArray = new int[4]; uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32); uuidArray[1] = (int) uuid.getMostSignificantBits(); diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java index c7e2f9f28..e83f135de 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NamedTag.java @@ -30,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull; public class NamedTag { private final String name; - private final Tag tag; + private final Tag tag; /** * Create a new named tag. @@ -38,7 +38,7 @@ public class NamedTag { * @param name the name * @param tag the tag */ - public NamedTag(String name, Tag tag) { + public NamedTag(String name, Tag tag) { checkNotNull(name); checkNotNull(tag); this.name = name; @@ -59,7 +59,7 @@ public class NamedTag { * * @return the tag */ - public Tag getTag() { + public Tag getTag() { return tag; } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java index abbd06b3f..d0b9590fa 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ShortTag.java @@ -19,41 +19,32 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.ShortBinaryTag; +import com.fastasyncworldedit.core.jnbt.NumberTag; +import org.enginehub.linbus.tree.LinShortTag; /** * The {@code TAG_Short} tag. * - * @deprecated Use {@link ShortBinaryTag}. + * @deprecated Use {@link LinShortTag}. */ @Deprecated -public final class ShortTag extends Tag { - - private final ShortBinaryTag innerTag; - +public final class ShortTag extends NumberTag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public ShortTag(short value) { - super(); - this.innerTag = ShortBinaryTag.of(value); + super(LinShortTag.of(value)); } - public ShortTag(ShortBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public ShortBinaryTag asBinaryTag() { - return this.innerTag; + public ShortTag(LinShortTag tag) { + super(tag); } @Override public Short getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java index 483263752..2bc78f141 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/StringTag.java @@ -19,44 +19,33 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; +import org.enginehub.linbus.tree.LinStringTag; import static com.google.common.base.Preconditions.checkNotNull; /** * The {@code TAG_String} tag. * - * @deprecated Use {@link StringBinaryTag}. + * @deprecated Use {@link LinStringTag}. */ @Deprecated -public final class StringTag extends Tag { - - private final StringBinaryTag innerTag; - +public final class StringTag extends Tag { /** * Creates the tag with an empty name. * * @param value the value of the tag */ public StringTag(String value) { - super(); - checkNotNull(value); - this.innerTag = StringBinaryTag.of(value); + super(LinStringTag.of(checkNotNull(value))); } - public StringTag(StringBinaryTag adventureTag) { - super(); - this.innerTag = adventureTag; - } - - @Override - public StringBinaryTag asBinaryTag() { - return this.innerTag; + public StringTag(LinStringTag tag) { + super(tag); } @Override public String getValue() { - return innerTag.value(); + return linTag.value(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java b/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java index 6327f4133..80df4c1cb 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/Tag.java @@ -19,26 +19,43 @@ package com.sk89q.jnbt; -import com.sk89q.worldedit.util.nbt.BinaryTagLike; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.ToLinTag; + +import javax.annotation.Nonnull; /** * Represents a NBT tag. * - * @deprecated JNBT is being removed for adventure-nbt in WorldEdit 8. + * @deprecated JNBT is being removed for lin-bus in WorldEdit 8, use {@link LinTag} instead */ -@Deprecated(forRemoval = true) -public abstract class Tag implements BinaryTagLike { +@Deprecated +public abstract class Tag> implements ToLinTag { + + protected final LT linTag; + + protected Tag(LT linTag) { + this.linTag = linTag; + } /** * Gets the value of this tag. * * @return the value */ - public abstract Object getValue(); + public V getValue() { + return linTag.value(); + } @Override public String toString() { - return asBinaryTag().toString(); + return toLinTag().toString(); + } + + @Override + @Nonnull + public LT toLinTag() { + return linTag; } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java b/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java index d4cc816e7..a894cbe14 100644 --- a/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java +++ b/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLNode.java @@ -161,28 +161,28 @@ public class YAMLNode { if (value instanceof Vector3) { Map out = new LinkedHashMap<>(); Vector3 vec = (Vector3) value; - out.put("x", vec.getX()); - out.put("y", vec.getY()); - out.put("z", vec.getZ()); + out.put("x", vec.x()); + out.put("y", vec.y()); + out.put("z", vec.z()); return out; } else if (value instanceof BlockVector3) { Map out = new LinkedHashMap<>(); BlockVector3 vec = (BlockVector3) value; - out.put("x", vec.getBlockX()); - out.put("y", vec.getBlockY()); - out.put("z", vec.getBlockZ()); + out.put("x", vec.x()); + out.put("y", vec.y()); + out.put("z", vec.z()); return out; } else if (value instanceof Vector2) { Map out = new LinkedHashMap<>(); Vector2 vec = (Vector2) value; - out.put("x", vec.getX()); - out.put("z", vec.getZ()); + out.put("x", vec.x()); + out.put("z", vec.z()); return out; } else if (value instanceof BlockVector2) { Map out = new LinkedHashMap<>(); BlockVector2 vec = (BlockVector2) value; - out.put("x", vec.getBlockX()); - out.put("z", vec.getBlockZ()); + out.put("x", vec.x()); + out.put("z", vec.z()); return out; } diff --git a/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java b/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java index 146428c3e..f50bd991f 100644 --- a/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java +++ b/worldedit-core/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java @@ -98,6 +98,8 @@ public class YAMLProcessor extends YAMLNode { LoaderOptions loaderOptions = new LoaderOptions(); try { + int yamlAliasLimit = Integer.getInteger("worldedit.yaml.aliasLimit", 50); + loaderOptions.setMaxAliasesForCollections(yamlAliasLimit); // 64 MB default int yamlCodePointLimit = Integer.getInteger("worldedit.yaml.codePointLimit", 64 * 1024 * 1024); loaderOptions.setCodePointLimit(yamlCodePointLimit); @@ -105,7 +107,7 @@ public class YAMLProcessor extends YAMLNode { // pre-1.32 snakeyaml } - yaml = new Yaml(new SafeConstructor(new LoaderOptions()), representer, dumperOptions, loaderOptions); + yaml = new Yaml(new SafeConstructor(loaderOptions), representer, dumperOptions, loaderOptions); this.file = file; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index ecf859896..b66b98897 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -38,7 +38,7 @@ import com.fastasyncworldedit.core.function.generator.GenBase; import com.fastasyncworldedit.core.function.generator.OreGen; import com.fastasyncworldedit.core.function.generator.SchemGen; import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder; -import com.fastasyncworldedit.core.function.mask.MaskUnion; +import com.sk89q.worldedit.function.mask.MaskUnion; import com.fastasyncworldedit.core.function.mask.ResettableMask; import com.fastasyncworldedit.core.function.mask.SingleBlockTypeMask; import com.fastasyncworldedit.core.function.mask.WallMakeMask; @@ -127,6 +127,7 @@ import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionIntersection; +import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape; @@ -308,16 +309,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @return Limit remaining */ public FaweLimit getLimitUsed() { - FaweLimit newLimit = new FaweLimit(); - newLimit.MAX_ACTIONS = originalLimit.MAX_ACTIONS - limit.MAX_ACTIONS; - newLimit.MAX_CHANGES = originalLimit.MAX_CHANGES - limit.MAX_CHANGES; - newLimit.MAX_FAILS = originalLimit.MAX_FAILS - limit.MAX_FAILS; - newLimit.MAX_CHECKS = originalLimit.MAX_CHECKS - limit.MAX_CHECKS; - newLimit.MAX_ITERATIONS = originalLimit.MAX_ITERATIONS - limit.MAX_ITERATIONS; - newLimit.MAX_BLOCKSTATES = originalLimit.MAX_BLOCKSTATES - limit.MAX_BLOCKSTATES; - newLimit.MAX_ENTITIES = originalLimit.MAX_ENTITIES - limit.MAX_ENTITIES; - newLimit.MAX_HISTORY = limit.MAX_HISTORY; - return newLimit; + return originalLimit.getLimitUsed(limit); } /** @@ -472,7 +464,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { */ @Deprecated public long getBlockChangeLimit() { - return originalLimit.MAX_CHANGES; + return originalLimit.MAX_CHANGES.get(); } /** @@ -481,7 +473,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @param limit the limit (>= 0) or -1 for no limit */ public void setBlockChangeLimit(long limit) { - this.limit.MAX_CHANGES = limit; + this.limit.MAX_CHANGES.set(limit); } /** @@ -903,7 +895,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { //FAWE start - use extent - if (position.getY() < this.minY || position.getY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } this.changes++; @@ -984,7 +976,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { public > boolean setBlock(BlockVector3 position, B block, Stage stage) throws WorldEditException { //FAWE start - accumulate changes - if (position.getBlockY() < this.minY || position.getBlockY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } @@ -1014,7 +1006,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { */ @Deprecated public > boolean rawSetBlock(BlockVector3 position, B block) { - if (position.getBlockY() < this.minY || position.getBlockY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } @@ -1037,7 +1029,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @return whether the block changed */ public > boolean smartSetBlock(BlockVector3 position, B block) { - if (position.getBlockY() < this.minY || position.getBlockY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } @@ -1052,7 +1044,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { @Override @Deprecated public > boolean setBlock(BlockVector3 position, B block) throws MaxChangedBlocksException { - if (position.getBlockY() < this.minY || position.getBlockY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } @@ -1114,7 +1106,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public boolean setBlock(BlockVector3 position, Pattern pattern) throws MaxChangedBlocksException { - if (position.getBlockY() < this.minY || position.getBlockY() > this.maxY) { + if (position.y() < this.minY || position.y() > this.maxY) { return false; } @@ -1293,8 +1285,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { Operations.completeBlindly(commit()); // Check fails FaweLimit used = getLimitUsed(); - if (used.MAX_FAILS > 0) { - if (used.MAX_CHANGES > 0 || used.MAX_ENTITIES > 0) { + if (used.MAX_FAILS.get() > 0) { + if (used.MAX_CHANGES.get() > 0 || used.MAX_ENTITIES.get() > 0) { actor.print(Caption.of("fawe.error.worldedit.some.fails", used.MAX_FAILS)); } else if (new ExtentTraverser<>(getExtent()).findAndGet(FaweRegionExtent.class) != null) { actor.print(Caption.of("fawe.cancel.reason.outside.region")); @@ -1349,12 +1341,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { public > int fall(final Region region, boolean fullHeight, final B replace) { FlatRegion flat = asFlatRegion(region); - final int startPerformY = region.getMinimumPoint().getBlockY(); + final int startPerformY = region.getMinimumPoint().y(); final int startCheckY = fullHeight ? getMinY() : startPerformY; - final int endY = region.getMaximumPoint().getBlockY(); + final int endY = region.getMaximumPoint().y(); RegionVisitor visitor = new RegionVisitor(flat, pos -> { - int x = pos.getX(); - int z = pos.getZ(); + int x = pos.x(); + int z = pos.z(); int freeSpot = startCheckY; for (int y = startCheckY; y <= endY; y++) { if (y < startPerformY) { @@ -1479,8 +1471,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { // Avoid int overflow (negative coordinate space allows for overflow back round to positive if the depth is large enough). // Depth is always 1 or greater, thus the lower bound should always be <= origin y. - int lowerBound = origin.getBlockY() - depth + 1; - if (lowerBound > origin.getBlockY()) { + int lowerBound = origin.y() - depth + 1; + if (lowerBound > origin.y()) { lowerBound = Integer.MIN_VALUE; } @@ -1488,7 +1480,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))), new BoundedHeightMask( Math.max(lowerBound, minY), - Math.min(maxY, origin.getBlockY()) + Math.min(maxY, origin.y()) ), Masks.negate(new ExistingBlockMask(this)) ); @@ -1502,7 +1494,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { if (recursive) { visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), minY, maxY, this); } else { - visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), minY, maxY, this); + visitor = new DownwardVisitor(mask, replace, origin.y(), (int) (radius * 2 + 1), minY, maxY, this); } //FAWE end @@ -1600,11 +1592,11 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { Vector3 center = region.getCenter(); Region centerRegion = new CuboidRegion( getWorld(), // Causes clamping of Y range - BlockVector3.at(((int) center.getX()), ((int) center.getY()), ((int) center.getZ())), + BlockVector3.at(((int) center.x()), ((int) center.y()), ((int) center.z())), BlockVector3.at( - MathUtils.roundHalfUp(center.getX()), - MathUtils.roundHalfUp(center.getY()), - MathUtils.roundHalfUp(center.getZ()) + MathUtils.roundHalfUp(center.x()), + MathUtils.roundHalfUp(center.y()), + MathUtils.roundHalfUp(center.z()) ) ); return setBlocks(centerRegion, pattern); @@ -1754,8 +1746,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { BlockReplace replace = new BlockReplace(this, pattern); RegionOffset offset = new RegionOffset(BlockVector3.UNIT_Y, replace); //FAWE start - int minY = region.getMinimumPoint().getBlockY(); - int maxY = Math.min(getMaximumPoint().getBlockY(), region.getMaximumPoint().getBlockY() + 1); + int minY = region.getMinimumPoint().y(); + int maxY = Math.min(getMaximumPoint().y(), region.getMaximumPoint().y() + 1); SurfaceRegionFunction surface = new SurfaceRegionFunction(this, offset, minY, maxY); FlatRegionVisitor visitor = new FlatRegionVisitor(asFlatRegion(region), surface, this); //FAWE end @@ -1813,18 +1805,59 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public int stackCuboidRegion( - Region region, BlockVector3 offset, int count, - boolean copyEntities, boolean copyBiomes, Mask mask + Region region, + BlockVector3 offset, + int count, + boolean copyEntities, + boolean copyBiomes, + Mask mask ) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(offset); + + BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); + try { + return stackRegionBlockUnits(region, offset.multiply(size), count, copyEntities, copyBiomes, mask); + } catch (RegionOperationException e) { + // Should never be able to happen + throw new AssertionError(e); + } + } + + /** + * Stack a region using block units. + * + * @param region the region to stack + * @param offset how far to move the contents each stack in block units + * @param count the number of times to stack + * @param copyEntities true to copy entities + * @param copyBiomes true to copy biomes + * @param mask source mask for the operation (only matching blocks are copied) + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + * @throws RegionOperationException thrown if the region operation is invalid + */ + public int stackRegionBlockUnits( + Region region, + BlockVector3 offset, + int count, + boolean copyEntities, + boolean copyBiomes, + Mask mask + ) throws MaxChangedBlocksException, RegionOperationException { + checkNotNull(region); + checkNotNull(offset); checkArgument(count >= 1, "count >= 1 required"); BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); + BlockVector3 offsetAbs = offset.abs(); + if (offsetAbs.x() < size.x() && offsetAbs.y() < size.y() && offsetAbs.z() < size.z()) { + throw new RegionOperationException(Caption.of("worldedit.stack.intersecting-region")); + } BlockVector3 to = region.getMinimumPoint(); ForwardExtentCopy copy = new ForwardExtentCopy(this, region, this, to); copy.setRepetitions(count); - copy.setTransform(new AffineTransform().translate(offset.multiply(size))); + copy.setTransform(new AffineTransform().translate(offset)); copy.setCopyingEntities(copyEntities); copy.setCopyingBiomes(copyBiomes); final Region allowedRegion; @@ -1905,7 +1938,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { BlockVector3 disAbs = displace.abs(); - if (disAbs.getBlockX() < size.getBlockX() && disAbs.getBlockY() < size.getBlockY() && disAbs.getBlockZ() < size.getBlockZ()) { + if (disAbs.x() < size.x() && disAbs.y() < size.y() && disAbs.z() < size.z()) { // Buffer if overlapping enableQueue(); } @@ -2068,7 +2101,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { // There are boundaries that the routine needs to stay in Mask mask = new MaskIntersection( - new BoundedHeightMask(minY, Math.min(origin.getBlockY(), maxY)), + new BoundedHeightMask(minY, Math.min(origin.y(), maxY)), new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))), blockMask ); @@ -2156,15 +2189,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } else if (height < 0) { height = -height; //FAWE start - mutableBlockVector3.mutY(mutableBlockVector3.getY() - height); + mutableBlockVector3.mutY(mutableBlockVector3.y() - height); //FAWE end } //FAWE start - if (mutableBlockVector3.getBlockY() < getWorld().getMinY()) { + if (mutableBlockVector3.y() < getWorld().getMinY()) { mutableBlockVector3.mutY(world.getMinY()); - } else if (mutableBlockVector3.getBlockY() + height - 1 > maxY) { - height = maxY - mutableBlockVector3.getBlockY() + 1; + } else if (mutableBlockVector3.y() + height - 1 > maxY) { + height = maxY - mutableBlockVector3.y() + 1; } //FAWE end @@ -2172,9 +2205,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final double invRadiusZ = 1 / radiusZ; //FAWE start - int px = mutableBlockVector3.getBlockX(); - int py = mutableBlockVector3.getBlockY(); - int pz = mutableBlockVector3.getBlockZ(); + int px = mutableBlockVector3.x(); + int py = mutableBlockVector3.y(); + int pz = mutableBlockVector3.z(); final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusZ = (int) Math.ceil(radiusZ); @@ -2319,9 +2352,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { double ry2 = Math.pow(height, 2); double rz2 = Math.pow(radiusZ, 2); - int cx = pos.getX(); - int cy = pos.getY(); - int cz = pos.getZ(); + int cx = pos.x(); + int cy = pos.y(); + int cz = pos.z(); for (int y = 0; y < height; ++y) { double ySquaredMinusHeightOverHeightSquared = Math.pow(y - height, 2) / ry2; @@ -2403,18 +2436,18 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { radiusZ += 0.5; normal = normal.normalize(); - double nx = normal.getX(); - double ny = normal.getY(); - double nz = normal.getZ(); + double nx = normal.x(); + double ny = normal.y(); + double nz = normal.z(); final double invRadiusX = 1 / radiusX; final double invRadiusY = 1 / radiusY; final double invRadiusZ = 1 / radiusZ; - int px = pos.getBlockX(); - int py = pos.getBlockY(); - int pz = pos.getBlockZ(); + int px = pos.x(); + int py = pos.y(); + int pz = pos.z(); final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusY = (int) Math.ceil(radiusY); @@ -2545,9 +2578,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final double invRadiusY = 1 / radiusY; final double invRadiusZ = 1 / radiusZ; - int px = pos.getBlockX(); - int py = pos.getBlockY(); - int pz = pos.getBlockZ(); + int px = pos.x(); + int py = pos.y(); + int pz = pos.z(); final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusY = (int) Math.ceil(radiusY); @@ -2654,9 +2687,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { */ public int makePyramid(BlockVector3 position, Pattern block, int size, boolean filled) throws MaxChangedBlocksException { //FAWE start - abbreviated logic - int bx = position.getX(); - int by = position.getY(); - int bz = position.getZ(); + int bx = position.x(); + int by = position.y(); + int bz = position.z(); int height = size; int yy, xx, x_x, zz, z_z; @@ -2715,9 +2748,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { int affected = 0; double radiusSq = radius * radius; - int ox = position.getBlockX(); - int oy = position.getBlockY(); - int oz = position.getBlockZ(); + int ox = position.x(); + int oy = position.y(); + int oz = position.z(); BlockState air = BlockTypes.AIR.getDefaultState(); BlockState water = BlockTypes.WATER.getDefaultState(); @@ -2755,7 +2788,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { if (setBlock(mutable, air)) { if (y > getMinY()) { BlockState block = getBlock(mutable2); - if (block.getStates().containsKey(snowy)) { + if (block.getBlockType().hasProperty(snowy)) { if (setBlock(mutable2, block.with(snowy, false))) { affected++; } @@ -2804,7 +2837,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { public int simulateSnow(BlockVector3 position, double radius, int height) throws MaxChangedBlocksException { - return simulateSnow(new CylinderRegion(position, Vector2.at(radius, radius), position.getBlockY(), height), false); + return simulateSnow(new CylinderRegion(position, Vector2.at(radius, radius), position.y(), height), false); } /** @@ -2860,9 +2893,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { int affected = 0; final double radiusSq = radius * radius; - final int ox = position.getBlockX(); - final int oy = position.getBlockY(); - final int oz = position.getBlockZ(); + final int ox = position.x(); + final int oy = position.y(); + final int oz = position.z(); final BlockState grass = BlockTypes.GRASS_BLOCK.getDefaultState(); @@ -3077,13 +3110,13 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } } if (expression.evaluate( - new double[]{scaled.getX(), scaled.getY(), scaled.getZ(), typeVar, dataVar}, + new double[]{scaled.x(), scaled.y(), scaled.z(), typeVar, dataVar}, timeout ) <= 0) { return null; } - int newType = (int) typeVariable.getValue(); - int newData = (int) dataVariable.getValue(); + int newType = (int) typeVariable.value(); + int newData = (int) dataVariable.value(); if (newType != typeVar || newData != dataVar) { BlockState state = LegacyMapper.getInstance().getBlockFromLegacy(newType, newData); return state == null ? defaultMaterial : state.toBaseBlock(); @@ -3180,10 +3213,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final Vector3 scaled = position.toVector3().subtract(zero).divide(unit); // transform - expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout); - int xv = (int) Math.floor(x.getValue() * unit.getX() + zero2.getX()); - int yv = (int) Math.floor(y.getValue() * unit.getY() + zero2.getY()); - int zv = (int) Math.floor(z.getValue() * unit.getZ() + zero2.getZ()); + expression.evaluate(new double[]{scaled.x(), scaled.y(), scaled.z()}, timeout); + int xv = (int) Math.floor(x.value() * unit.x() + zero2.x()); + int yv = (int) Math.floor(y.value() * unit.y() + zero2.y()); + int zv = (int) Math.floor(z.value() * unit.z() + zero2.z()); BlockState get; if (yv >= minY && yv <= maxY) { @@ -3222,12 +3255,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final BlockVector3 min = region.getMinimumPoint(); final BlockVector3 max = region.getMaximumPoint(); - final int minX = min.getBlockX(); - final int minY = min.getBlockY(); - final int minZ = min.getBlockZ(); - final int maxX = max.getBlockX(); - final int maxY = max.getBlockY(); - final int maxZ = max.getBlockZ(); + final int minX = min.x(); + final int minY = min.y(); + final int minZ = min.z(); + final int maxX = max.x(); + final int maxY = max.y(); + final int maxZ = max.z(); //FAWE start - mutable MutableBlockVector3 mutable = new MutableBlockVector3(); @@ -3316,12 +3349,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, double radius, boolean filled, boolean flat) throws MaxChangedBlocksException { - int x1 = pos1.getBlockX(); - int y1 = pos1.getBlockY(); - int z1 = pos1.getBlockZ(); - int x2 = pos2.getBlockX(); - int y2 = pos2.getBlockY(); - int z2 = pos2.getBlockZ(); + int x1 = pos1.x(); + int y1 = pos1.y(); + int z1 = pos1.z(); + int x2 = pos2.x(); + int y2 = pos2.y(); + int z2 = pos2.z(); int tipx = x1; int tipy = y1; int tipz = z1; @@ -3416,12 +3449,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { BlockVector3 pos1 = vectors.get(i); BlockVector3 pos2 = vectors.get(i + 1); - int x1 = pos1.getBlockX(); - int y1 = pos1.getBlockY(); - int z1 = pos1.getBlockZ(); - int x2 = pos2.getBlockX(); - int y2 = pos2.getBlockY(); - int z2 = pos2.getBlockZ(); + int x1 = pos1.x(); + int y1 = pos1.y(); + int z1 = pos1.z(); + int x2 = pos2.x(); + int y2 = pos2.y(); + int z2 = pos2.z(); int tipx = x1; int tipy = y1; int tipz = z1; @@ -3532,9 +3565,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { int ceilrad = (int) Math.ceil(radius); for (BlockVector3 v : vset) { - int tipx = v.getBlockX(); - int tipy = v.getBlockY(); - int tipz = v.getBlockZ(); + int tipx = v.x(); + int tipy = v.y(); + int tipz = v.z(); for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) { for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) { @@ -3557,13 +3590,13 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final LocalBlockVectorSet returnset = new LocalBlockVectorSet(); final int ceilrad = (int) Math.ceil(radius); for (BlockVector3 v : vset) { - final int tipx = v.getBlockX(); - final int tipy = v.getBlockY(); - final int tipz = v.getBlockZ(); + final int tipx = v.x(); + final int tipy = v.y(); + final int tipz = v.z(); for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) { for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) { if (MathMan.hypot(loopx - tipx, 0, loopz - tipz) <= radius) { - returnset.add(loopx, v.getBlockY(), loopz); + returnset.add(loopx, v.y(), loopz); } } } @@ -3576,9 +3609,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final LocalBlockVectorSet newset = new LocalBlockVectorSet(); newset.addAll(vset); for (BlockVector3 v : newset) { - final int x = v.getX(); - final int y = v.getY(); - final int z = v.getZ(); + final int x = v.x(); + final int y = v.y(); + final int z = v.z(); if (!(newset.contains(x + 1, y, z) && newset.contains(x - 1, y, z) && newset.contains(x, y, z + 1) @@ -3595,9 +3628,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { final LocalBlockVectorSet newset = new LocalBlockVectorSet(); newset.addAll(vset); for (BlockVector3 v : newset) { - final int x = v.getX(); - final int y = v.getY(); - final int z = v.getZ(); + final int x = v.x(); + final int y = v.y(); + final int z = v.z(); if (!(newset.contains(x + 1, y, z) && newset.contains(x - 1, y, z) && newset.contains(x, y + 1, z) @@ -3611,7 +3644,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } private void recurseHollow(Region region, BlockVector3 origin, Set outside, Mask mask) { - final LocalBlockVectorSet queue = new LocalBlockVectorSet(); + // FAWE start - use BlockVector3Set instead of LinkedList + final BlockVector3Set queue = BlockVector3Set.getAppropriateVectorSet(region); queue.add(origin); while (!queue.isEmpty()) { @@ -3634,6 +3668,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } } } + // FAWE end } public int makeBiomeShape( @@ -3668,9 +3703,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { @Override protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) { environment.setCurrentBlock(x, y, z); - double scaledX = (x - zero.getX()) / unit.getX(); - double scaledY = (y - zero.getY()) / unit.getY(); - double scaledZ = (z - zero.getZ()) / unit.getZ(); + double scaledX = (x - zero.x()) / unit.x(); + double scaledY = (y - zero.y()) / unit.y(); + double scaledZ = (z - zero.z()) / unit.z(); try { if (expression.evaluate(new double[]{scaledX, scaledY, scaledZ}, timeout) <= 0) { @@ -3717,9 +3752,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } private void setExistingBlocks(BlockVector3 pos1, BlockVector3 pos2) { - for (int x = pos1.getX(); x <= pos2.getX(); x++) { - for (int z = pos1.getBlockZ(); z <= pos2.getBlockZ(); z++) { - for (int y = pos1.getY(); y <= pos2.getY(); y++) { + for (int x = pos1.x(); x <= pos2.x(); x++) { + for (int z = pos1.z(); z <= pos2.z(); z++) { + for (int y = pos1.y(); y <= pos2.y(); y++) { setBlock(x, y, z, getFullBlock(x, y, z)); } } @@ -3735,10 +3770,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { if (fe != null && cuboid) { BlockVector3 max = region.getMaximumPoint(); BlockVector3 min = region.getMinimumPoint(); - if (!fe.contains(max.getBlockX(), max.getBlockY(), max.getBlockZ()) && !fe.contains( - min.getBlockX(), - min.getBlockY(), - min.getBlockZ() + if (!fe.contains(max.x(), max.y(), max.z()) && !fe.contains( + min.x(), + min.y(), + min.z() )) { throw FaweCache.OUTSIDE_REGION; } @@ -3748,17 +3783,17 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { MutableBlockVector3 mutable2 = new MutableBlockVector3(); MutableBlockVector2 mutable2D = new MutableBlockVector2(); for (BlockVector2 chunk : chunks) { - final int cx = chunk.getBlockX(); - final int cz = chunk.getBlockZ(); + final int cx = chunk.x(); + final int cz = chunk.z(); final int bx = cx << 4; final int bz = cz << 4; final BlockVector3 cmin = BlockVector3.at(bx, 0, bz); final BlockVector3 cmax = cmin.add(15, maxY, 15); final boolean containsBot1 = - fe == null || fe.contains(cmin.getBlockX(), cmin.getBlockY(), cmin.getBlockZ()); + fe == null || fe.contains(cmin.x(), cmin.y(), cmin.z()); final boolean containsBot2 = region.contains(cmin); final boolean containsTop1 = - fe == null || fe.contains(cmax.getBlockX(), cmax.getBlockY(), cmax.getBlockZ()); + fe == null || fe.contains(cmax.x(), cmax.y(), cmax.z()); final boolean containsTop2 = region.contains(cmax); if (containsBot2 && containsTop2 && !containsBot1 && !containsTop1) { continue; @@ -3881,7 +3916,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { @Override public void addSchems(Region region, Mask mask, List clipboards, int rarity, boolean rotate) throws WorldEditException { - spawnResource(region, new SchemGen(mask, this, clipboards, rotate), rarity, 1); + spawnResource(region, new SchemGen(mask, this, clipboards, rotate, region), rarity, 1); } @Override @@ -3917,15 +3952,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { double seedY = ThreadLocalRandom.current().nextDouble(); double seedZ = ThreadLocalRandom.current().nextDouble(); - int px = position.getBlockX(); - int py = position.getBlockY(); - int pz = position.getBlockZ(); + int px = position.x(); + int py = position.y(); + int pz = position.z(); double distort = frequency / size; - double modX = 1d / radius.getX(); - double modY = 1d / radius.getY(); - double modZ = 1d / radius.getZ(); + double modX = 1d / radius.x(); + double modY = 1d / radius.y(); + double modZ = 1d / radius.z(); int r = (int) size; int radiusSqr = (int) (size * size); int sizeInt = (int) size * 2; @@ -3986,9 +4021,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { // so it must be set each time mutable.setComponents(xr, yr, zr); Vector3 pt = transform.apply(mutable); - x = MathMan.roundInt(pt.getX()); - y = MathMan.roundInt(pt.getY()); - z = MathMan.roundInt(pt.getZ()); + x = MathMan.roundInt(pt.x()); + y = MathMan.roundInt(pt.y()); + z = MathMan.roundInt(pt.z()); xScaled = Math.abs(x) * modX; yScaled = Math.abs(y) * modY; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java index ca6f3b6a5..26650bf9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java @@ -635,7 +635,11 @@ public final class EditSessionBuilder { }; } if (limit != null && !limit.isUnlimited()) { - this.extent = new LimitExtent(this.extent, limit, onErrorMessage); + this.extent = new LimitExtent(this.extent, limit, onErrorMessage, placeChunks && combineStages); + // Only process if we're not necessarily going to catch tiles via Extent#setBlock, e.g. because using PQE methods + if (placeChunks && combineStages) { + queue.addProcessor((LimitExtent) this.extent); + } } this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalConfiguration.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalConfiguration.java index 57ec6f186..1301c5bb3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalConfiguration.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalConfiguration.java @@ -52,12 +52,26 @@ import java.util.Set; public abstract class LocalConfiguration { private static final Logger LOGGER = LogManagerCompat.getLogger(); + //FAWE start - inelegant but required to transfer to FAWE limits as defaults + public static int MAX_RADIUS; + public static int MAX_SUPER_RADIUS; + public static int MAX_BRUSH_RADIUS; + public static int MAX_BUTCHER_RADIUS; + //FAWE end public boolean profile = false; public boolean traceUnflushedSessions = true; public Set disallowedBlocks = new HashSet<>(); protected BlockMask disallowedBlocksMask; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_CHANGES} + */ + @Deprecated public int defaultChangeLimit = -1; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_CHANGES} + */ + @Deprecated public int maxChangeLimit = -1; public int defaultVerticalHeight = 256; public int defaultMaxPolygonalPoints = -1; @@ -68,8 +82,20 @@ public abstract class LocalConfiguration { public boolean snapshotsConfigured = false; public SnapshotRepository snapshotRepo = null; public SnapshotDatabase snapshotDatabase = null; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_RADIUS} + */ + @Deprecated public int maxRadius = -1; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_SUPER_PICKAXE_SIZE} + */ + @Deprecated public int maxSuperPickaxeSize = 5; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_BRUSH_RADIUS} + */ + @Deprecated public int maxBrushRadius = 6; public boolean logCommands = false; public String logFile = ""; @@ -92,6 +118,10 @@ public abstract class LocalConfiguration { public String scriptsDir = "craftscripts"; public boolean showHelpInfo = true; // unused public int butcherDefaultRadius = -1; + /** + * @deprecated Use actor's limit {@link com.fastasyncworldedit.core.limit.FaweLimit#MAX_BUTCHER_RADIUS} + */ + @Deprecated public int butcherMaxRadius = -1; public boolean allowSymlinks = false; public boolean serverSideCUI = true; @@ -166,7 +196,7 @@ public abstract class LocalConfiguration { BlockTypes.BEDROCK FAWE end*/ ); - return blockTypes.stream().filter(Objects::nonNull).map(BlockType::getId).toArray(String[]::new); + return blockTypes.stream().filter(Objects::nonNull).map(BlockType::id).toArray(String[]::new); } /** @@ -247,7 +277,7 @@ public abstract class LocalConfiguration { id = Integer.parseInt(splitter[0]); data = Byte.parseByte(splitter[1]); } - item = LegacyMapper.getInstance().getItemFromLegacy(id, data).getId(); + item = LegacyMapper.getInstance().getItemFromLegacy(id, data).id(); } catch (Throwable ignored) { } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 3391bad80..006de1b0b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -32,7 +32,9 @@ import com.fastasyncworldedit.core.internal.io.FaweOutputStream; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.util.BrushCache; import com.fastasyncworldedit.core.util.MainUtil; +import com.fastasyncworldedit.core.util.MaskTraverser; import com.fastasyncworldedit.core.util.StringMan; +import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TextureHolder; import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.wrappers.WorldWrapper; @@ -50,8 +52,10 @@ import com.sk89q.worldedit.command.tool.SelectionWand; import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Locatable; +import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -72,15 +76,15 @@ import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.snapshot.experimental.Snapshot; import com.zaxxer.sparsebits.SparseBitSet; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -99,7 +103,6 @@ import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -123,7 +126,9 @@ public class LocalSession implements TextureHolder { private transient int cuiVersion = CUI_VERSION_UNINITIALIZED; // Session related - private transient RegionSelector selector = new CuboidRegionSelector(); + //FAWE start - allow saving to session store + private RegionSelector selector = new CuboidRegionSelector(); + //FAWE end private transient boolean placeAtPos1 = false; //FAWE start private final transient List history = Collections.synchronizedList(new LinkedList<>() { @@ -143,7 +148,7 @@ public class LocalSession implements TextureHolder { } }); private transient volatile Integer historyNegativeIndex; - private transient final Lock historyWriteLock = new ReentrantLock(true); + private transient final ReentrantLock historyWriteLock = new ReentrantLock(true); private final transient Int2ObjectOpenHashMap tools = new Int2ObjectOpenHashMap<>(0); private transient Mask sourceMask; private transient TextureUtil texture; @@ -178,8 +183,10 @@ public class LocalSession implements TextureHolder { private String lastScript; private RegionSelectorType defaultSelector; private boolean useServerCUI = false; // Save this to not annoy players. - private ItemType wandItem; - private ItemType navWandItem; + //FAWE start - allow NBT + private BaseItem wandItem; + private BaseItem navWandItem; + //FAWE end /** * Construct the object. @@ -405,6 +412,23 @@ public class LocalSession implements TextureHolder { */ public void clearHistory() { //FAWE start + boolean mainThread = Fawe.isMainThread(); + if (mainThread && !historyWriteLock.tryLock()) { + // Do not make main thread wait if we cannot immediately clear history (on player logout usually) + TaskManager.taskManager().async(this::clearHistoryTask); + return; + } + try { + clearHistoryTask(); + } finally { + // only if we are on the main thread, we ever called tryLock -> need to unlock again + if (mainThread) { + historyWriteLock.unlock(); + } + } + } + + private void clearHistoryTask() { historyWriteLock.lock(); try { // Ensure that changesets are properly removed @@ -420,8 +444,8 @@ public class LocalSession implements TextureHolder { save(); historySize = 0; currentWorld = null; - //FAWE end } + //FAWE end /** * Remember an edit session for the undo history. If the history maximum @@ -476,7 +500,7 @@ public class LocalSession implements TextureHolder { if (Settings.settings().HISTORY.USE_DISK) { LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE; } - if (changeSet.size() == 0) { + if (changeSet.longSize() == 0) { return; } loadSessionHistoryFromDisk(player.getUniqueId(), world); @@ -577,6 +601,9 @@ public class LocalSession implements TextureHolder { long size = MainUtil.getSize(item); historySize -= size; } + // free the mask from any remaining references to e.g. extents + // if used again + new MaskTraverser(mask).reset(NullExtent.INSTANCE); } finally { historyWriteLock.unlock(); } @@ -749,6 +776,7 @@ public class LocalSession implements TextureHolder { checkNotNull(selector); selector.setWorld(world); this.selector = selector; + setDirty(); if (hasWorldOverride() && !world.equals(getWorldOverride())) { setWorldOverride(null); } @@ -902,7 +930,7 @@ public class LocalSession implements TextureHolder { } } catch (EmptyClipboardException ignored) { } - DiskOptimizedClipboard doc = Fawe.instance().getClipboardExecutor().submit( + DiskOptimizedClipboard doc = Fawe.instance().submitUUIDKeyQueuedTask( uuid, () -> DiskOptimizedClipboard.loadFromFile(file) ).get(); @@ -926,7 +954,7 @@ public class LocalSession implements TextureHolder { } else { continue; } - Fawe.instance().getClipboardExecutor().submit(uuid, () -> { + Fawe.instance().submitUUIDKeyQueuedTask(uuid, () -> { doc.close(); // Ensure closed before deletion doc.getFile().delete(); }); @@ -1174,7 +1202,7 @@ public class LocalSession implements TextureHolder { tool = tools.get(item.getInternalId()); } if (tool == SelectionWand.INSTANCE && !SelectionWand.INSTANCE.canUse(player)) { - tools.remove(wandItem.getInternalId()); + tools.remove(wandItem.getType().getInternalId()); loadDefaults(player, true); // Permissions have changed so redo the player's current tools. return null; } @@ -1228,18 +1256,20 @@ public class LocalSession implements TextureHolder { if (loadDefaults || force) { loadDefaults = false; LocalConfiguration config = WorldEdit.getInstance().getConfiguration(); + ParserContext context = new ParserContext(); + context.setActor(actor); if (wandItem == null) { - wandItem = ItemTypes.parse(config.wandItem); + wandItem = WorldEdit.getInstance().getItemFactory().parseFromInput(config.wandItem, context); } if (navWandItem == null) { - navWandItem = ItemTypes.parse(config.navigationWand); + navWandItem = WorldEdit.getInstance().getItemFactory().parseFromInput(config.navigationWand, context); } synchronized (this.tools) { - if (tools.get(navWandItem.getInternalId()) == null && NavigationWand.INSTANCE.canUse(actor)) { - tools.put(navWandItem.getInternalId(), NavigationWand.INSTANCE); + if (tools.get(navWandItem.getType().getInternalId()) == null && NavigationWand.INSTANCE.canUse(actor)) { + tools.put(navWandItem.getType().getInternalId(), NavigationWand.INSTANCE); } - if (tools.get(wandItem.getInternalId()) == null && SelectionWand.INSTANCE.canUse(actor)) { - tools.put(wandItem.getInternalId(), SelectionWand.INSTANCE); + if (tools.get(wandItem.getType().getInternalId()) == null && SelectionWand.INSTANCE.canUse(actor)) { + tools.put(wandItem.getType().getInternalId(), SelectionWand.INSTANCE); } } } @@ -1309,10 +1339,24 @@ public class LocalSession implements TextureHolder { * @param item the item type * @param tool the tool to set, which can be {@code null} * @throws InvalidToolBindException if the item can't be bound to that item + * @deprecated use {@link #setTool(BaseItem, Tool)} */ + @Deprecated public void setTool(ItemType item, @Nullable Tool tool) throws InvalidToolBindException { - if (item.hasBlockType()) { - throw new InvalidToolBindException(item, Caption.of("worldedit.error.blocks-cant-be-used")); + setTool(new BaseItem(item), tool); + } + + /** + * Set the tool. + * + * @param item the item type + * @param tool the tool to set, which can be {@code null} + * @throws InvalidToolBindException if the item can't be bound to that item + * @since 2.11.0 + */ + public void setTool(BaseItem item, @Nullable Tool tool) throws InvalidToolBindException { + if (item.getType().hasBlockType()) { + throw new InvalidToolBindException(item.getType(), Caption.of("worldedit.error.blocks-cant-be-used")); } if (tool instanceof SelectionWand) { changeTool(this.wandItem, this.wandItem = item, tool); @@ -1323,7 +1367,7 @@ public class LocalSession implements TextureHolder { setDirty(); return; } - setTool(item.getDefaultState(), tool, null); + setTool(item, tool, null); } public void setTool(Player player, @Nullable Tool tool) throws InvalidToolBindException { @@ -1331,17 +1375,17 @@ public class LocalSession implements TextureHolder { setTool(item, tool, player); } - private void changeTool(ItemType oldType, ItemType newType, Tool newTool) { - if (oldType != null) { + private void changeTool(BaseItem oldItem, BaseItem newItem, Tool newTool) { + if (oldItem != null) { synchronized (this.tools) { - this.tools.remove(oldType.getInternalId()); + this.tools.remove(oldItem.getType().getInternalId()); } } synchronized (this.tools) { if (newTool == null) { - this.tools.remove(newType.getInternalId()); + this.tools.remove(newItem.getType().getInternalId()); } else { - this.tools.put(newType.getInternalId(), newTool); + this.tools.put(newItem.getType().getInternalId(), newTool); } } } @@ -1351,11 +1395,11 @@ public class LocalSession implements TextureHolder { if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) { throw new InvalidToolBindException(type, Caption.of("worldedit.error.blocks-cant-be-used")); } else if (tool instanceof SelectionWand) { - changeTool(this.wandItem, this.wandItem = item.getType(), tool); + changeTool(this.wandItem, this.wandItem = item, tool); setDirty(); return; } else if (tool instanceof NavigationWand) { - changeTool(this.navWandItem, this.navWandItem = item.getType(), tool); + changeTool(this.navWandItem, this.navWandItem = item, tool); setDirty(); return; } @@ -1470,13 +1514,13 @@ public class LocalSession implements TextureHolder { BaseBlock block = ServerCUIHandler.createStructureBlock(player); if (block != null) { - CompoundBinaryTag tags = Objects.requireNonNull( - block.getNbt(), "createStructureBlock should return nbt" + LinCompoundTag tags = Objects.requireNonNull( + block.getNbt(), "createStructureBlock should return nbt" ); BlockVector3 tempCuiTemporaryBlock = BlockVector3.at( - tags.getInt("x"), - tags.getInt("y"), - tags.getInt("z") + tags.getTag("x", LinTagType.intTag()).valueAsInt(), + tags.getTag("y", LinTagType.intTag()).valueAsInt(), + tags.getTag("z", LinTagType.intTag()).valueAsInt() ); // If it's null, we don't need to do anything. The old was already removed. if (cuiTemporaryBlock != null && !tempCuiTemporaryBlock.equals(cuiTemporaryBlock)) { @@ -1681,6 +1725,7 @@ public class LocalSession implements TextureHolder { * @return an edit session */ public EditSession createEditSession(Actor actor) { + //FAWE start return createEditSession(actor, null); } @@ -1695,7 +1740,6 @@ public class LocalSession implements TextureHolder { } // Create an edit session - //FAWE start - we don't use the edit session builder yet EditSession editSession; EditSessionBuilder builder = WorldEdit.getInstance().newEditSessionBuilder().world(world); if (actor.isPlayer() && actor instanceof Player) { @@ -1852,20 +1896,46 @@ public class LocalSession implements TextureHolder { * Get the preferred wand item for this user, or {@code null} to use the default * * @return item id of wand item, or {@code null} + * @deprecated use {@link #getWandBaseItem()} */ + @Deprecated public String getWandItem() { - return wandItem.getId(); + return wandItem.getType().id(); } /** * Get the preferred navigation wand item for this user, or {@code null} to use the default * * @return item id of nav wand item, or {@code null} + * @deprecated use {@link #getNavWandBaseItem()} */ + @Deprecated public String getNavWandItem() { - return navWandItem.getId(); + return navWandItem.getType().id(); } + //FAWE start + /** + * Get the preferred wand item for this user, or {@code null} to use the default + * + * @return item id of wand item, or {@code null} + * @since 2.11.0 + */ + public BaseItem getWandBaseItem() { + return wandItem == null ? null : new BaseItem(wandItem.getType(), wandItem.getNbtReference()); + } + + /** + * Get the preferred navigation wand item for this user, or {@code null} to use the default + * + * @return item id of nav wand item, or {@code null} + * @since 2.11.0 + */ + public BaseItem getNavWandBaseItem() { + return navWandItem == null ? null : new BaseItem(navWandItem.getType(), navWandItem.getNbtReference()); + } + //FAWE end + /** * Get the last block distribution stored in this session. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/MaxBrushRadiusException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/MaxBrushRadiusException.java index 76a640c66..cb1371451 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/MaxBrushRadiusException.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/MaxBrushRadiusException.java @@ -19,9 +19,24 @@ package com.sk89q.worldedit; +import com.fastasyncworldedit.core.exception.BrushRadiusLimitException; +import com.fastasyncworldedit.core.exception.RadiusLimitException; + /** * Thrown when a maximum radius for a brush is reached. + * + * @deprecated Use {@link RadiusLimitException} */ +@Deprecated public class MaxBrushRadiusException extends MaxRadiusException { + //FAWE start + + /** + * @deprecated Use {@link BrushRadiusLimitException} + */ + @Deprecated + public MaxBrushRadiusException() { + } + //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/MaxRadiusException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/MaxRadiusException.java index 6641c063c..1e5da912f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/MaxRadiusException.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/MaxRadiusException.java @@ -19,10 +19,24 @@ package com.sk89q.worldedit; +import com.fastasyncworldedit.core.exception.RadiusLimitException; + /** * Thrown when a maximum radius is reached, such as, for example, * in the case of a sphere command. + * + * @deprecated Use {@link RadiusLimitException} */ +@Deprecated public class MaxRadiusException extends WorldEditException { + //FAWE start + /** + * @deprecated Use {@link RadiusLimitException} + */ + @Deprecated + public MaxRadiusException() { + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index b0f8ab1a5..085f52fcf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -20,6 +20,9 @@ package com.sk89q.worldedit; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.exception.BrushRadiusLimitException; +import com.fastasyncworldedit.core.exception.OutsideWorldBoundsException; +import com.fastasyncworldedit.core.exception.RadiusLimitException; import com.fastasyncworldedit.core.extension.factory.TransformFactory; import com.fastasyncworldedit.core.extent.ResettableExtent; import com.google.common.base.Throwables; @@ -44,6 +47,7 @@ import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Locatable; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.PlatformManager; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; @@ -437,7 +441,9 @@ public final class WorldEdit { * * @param radius the radius * @throws MaxRadiusException if the radius is bigger than the configured radius + * @deprecated Use {@link WorldEdit#checkMaxRadius(double, Actor)} */ + @Deprecated public void checkMaxRadius(double radius) throws MaxRadiusException { if (getConfiguration().maxRadius > 0 && radius > getConfiguration().maxRadius) { throw new MaxRadiusException(); @@ -449,7 +455,9 @@ public final class WorldEdit { * * @param radius the radius * @throws MaxBrushRadiusException if the radius is bigger than the configured radius + * @deprecated Use {@link WorldEdit#checkMaxBrushRadius(double, Actor)} */ + @Deprecated public void checkMaxBrushRadius(double radius) throws MaxBrushRadiusException { if (getConfiguration().maxBrushRadius > 0 && radius > getConfiguration().maxBrushRadius) { throw new MaxBrushRadiusException(); @@ -457,6 +465,10 @@ public final class WorldEdit { } //FAWE start + /** + * @deprecated Use {@link WorldEdit#checkMaxBrushRadius(Expression, Actor)} + */ + @Deprecated(forRemoval = true, since = "2.11.0") public void checkMaxBrushRadius(Expression radius) throws MaxBrushRadiusException { double val = radius.evaluate(); checkArgument(val >= 0, "Radius must be a positive number."); @@ -466,6 +478,67 @@ public final class WorldEdit { } } } + + /** + * Check the given radius against the give actor's limit. + * + * @param radius Radius to check + * @param actor Actor to check for + * @throws MaxRadiusException If given radius larger than allowed + * @since 2.11.0 + */ + public void checkMaxRadius(double radius, Actor actor) { + int max = actor.getLimit().MAX_RADIUS; + if (max > 0 && radius > max) { + throw new RadiusLimitException(max); + } + } + + /** + * Check the given radius against the give actor's limit. + * + * @param radius Radius to check + * @param actor Actor to check for + * @throws MaxRadiusException If given radius larger than allowed + * @since 2.11.0 + */ + public void checkMaxBrushRadius(double radius, Actor actor) { + int max = actor.getLimit().MAX_BRUSH_RADIUS; + if (max > 0 && radius > max) { + throw new RadiusLimitException(max); + } + } + + /** + * Check the given radius against the give actor's limit. + * + * @param expression Radius to check + * @param actor Actor to check for + * @throws BrushRadiusLimitException If given radius larger than allowed + * @since 2.11.0 + */ + public void checkMaxBrushRadius(Expression expression, Actor actor) { + double radius = expression.evaluate(); + checkArgument(radius >= 0, "Radius must be a positive number."); + int max = actor.getLimit().MAX_BRUSH_RADIUS; + if (max > 0 && radius > max) { + throw new BrushRadiusLimitException(max); + } + } + + /** + * Check if the given position is contained by the extent's min/max height + * + * @param position Position to check + * @param extent Extent to check in + * @throws OutsideWorldBoundsException If the position is outside the world height limits + * @since 2.11.0 + */ + public void checkExtentHeightBounds(BlockVector3 position, Extent extent) { + if (position.y() < extent.getMinY() || position.y() > extent.getMaxY()) { + throw new OutsideWorldBoundsException(position.y()); + } + } //FAWE end /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java index 9ce5c24f0..c7ffa7769 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java @@ -23,7 +23,7 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.UncheckedIOException; import java.net.JarURLConnection; -import java.net.URL; +import java.net.URI; import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -64,7 +64,7 @@ public class WorldEditManifest { } @Nullable - private static Attributes readAttributes() { + public static Attributes readAttributes() { Class clazz = WorldEditManifest.class; String className = clazz.getSimpleName() + ".class"; String classPath = clazz.getResource(className).toString(); @@ -73,8 +73,7 @@ public class WorldEditManifest { } try { - URL url = new URL(classPath); - JarURLConnection jarConnection = (JarURLConnection) url.openConnection(); + JarURLConnection jarConnection = (JarURLConnection) URI.create(classPath).toURL().openConnection(); Manifest manifest = jarConnection.getManifest(); return manifest.getMainAttributes(); } catch (IOException e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java index 1dab627c7..552dc6f56 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java @@ -20,15 +20,13 @@ package com.sk89q.worldedit.blocks; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.TagStringIO; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.item.ItemType; +import org.enginehub.linbus.format.snbt.LinStringIO; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; -import java.io.IOException; import static com.google.common.base.Preconditions.checkNotNull; @@ -42,9 +40,7 @@ public class BaseItem implements NbtValued { private ItemType itemType; @Nullable - //FAWE start - Use LR & CBT over CompoundTag - private LazyReference nbtData; - //FAWE end + private LazyReference nbtData; /** * Construct the object. @@ -56,6 +52,29 @@ public class BaseItem implements NbtValued { this.itemType = itemType; } + /** + * Construct the object. + * + * @param itemType Type of the item + * @param nbtData NBT Compound tag + */ + @Deprecated + public BaseItem(ItemType itemType, @Nullable CompoundTag nbtData) { + this(itemType, nbtData == null ? null : LazyReference.from(nbtData::toLinTag)); + } + + /** + * Construct the object. + * + * @param itemType Type of the item + * @param tag NBT Compound tag + */ + public BaseItem(ItemType itemType, @Nullable LazyReference tag) { + checkNotNull(itemType); + this.itemType = itemType; + this.nbtData = tag; + } + /** * Get the type of item. * @@ -71,34 +90,12 @@ public class BaseItem implements NbtValued { * @param itemType The type to set */ public void setType(ItemType itemType) { + checkNotNull(itemType); this.itemType = itemType; } //FAWE start - /** - * Construct the object. - * - * @param itemType Type of the item - * @param nbtData NBT Compound tag - */ - @Deprecated - public BaseItem(ItemType itemType, @Nullable CompoundTag nbtData) { - this(itemType, nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); - } - - /** - * Construct the object. - * - * @param itemType Type of the item - * @param tag NBT Compound tag - */ - public BaseItem(ItemType itemType, @Nullable LazyReference tag) { - checkNotNull(itemType); - this.itemType = itemType; - this.nbtData = tag; - } - @Deprecated @Nullable public Object getNativeItem() { @@ -107,28 +104,23 @@ public class BaseItem implements NbtValued { @Nullable @Override - public LazyReference getNbtReference() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbtReference(@Nullable LazyReference nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { this.nbtData = nbtData; } @Override public String toString() { String nbtString = ""; - LazyReference nbtData = this.nbtData; if (nbtData != null) { - try { - nbtString = TagStringIO.get().asString(nbtData.getValue()); - } catch (IOException e) { - WorldEdit.logger.error("Failed to serialize NBT of Item", e); - } + nbtString = LinStringIO.writeToString(nbtData.getValue()); } - return getType().getId() + nbtString; + return getType().id() + nbtString; } //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java index 07a9aa147..b83efe24a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java @@ -24,8 +24,8 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.item.ItemType; +import org.enginehub.linbus.tree.LinCompoundTag; /** * Represents a stack of BaseItems. @@ -70,6 +70,18 @@ public class BaseItemStack extends BaseItem { this.amount = amount; } + /** + * Construct the object. + * + * @param id The item type + * @param tag Tag value + * @param amount amount in the stack + */ + public BaseItemStack(ItemType id, LazyReference tag, int amount) { + super(id, tag); + this.amount = amount; + } + /** * Get the number of items in the stack. * @@ -93,18 +105,4 @@ public class BaseItemStack extends BaseItem { .getRegistries().getItemRegistry().getRichName(this); } - //FAWE start - - /** - * Construct the object. - * - * @param id The item type - * @param tag Tag value - * @param amount amount in the stack - */ - public BaseItemStack(ItemType id, LazyReference tag, int amount) { - super(id, tag); - this.amount = amount; - } - //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 0b2bd576d..1f551aefa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; @@ -98,7 +99,7 @@ public class BiomeCommands { PaginationBox paginationBox = PaginationBox.fromComponents("Available Biomes", "/biomelist -p %page%", BiomeType.REGISTRY.values().stream() .map(biomeType -> TextComponent.builder() - .append(biomeType.getId()) + .append(biomeType.id()) .append(" (") .append(biomeRegistry.getRichName(biomeType)) .append(")") @@ -166,7 +167,7 @@ public class BiomeCommands { List components = biomes.stream().map(biome -> biomeRegistry.getRichName(biome).hoverEvent( - HoverEvent.showText(TextComponent.of(biome.getId())) + HoverEvent.showText(TextComponent.of(biome.id())) ) ).collect(Collectors.toList()); actor.print(Caption.of(messageKey, TextUtils.join(components, TextComponent.of(", ")))); @@ -179,6 +180,7 @@ public class BiomeCommands { ) @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement @Confirm(Confirm.Processor.REGION) @CommandPermissions("worldedit.biome.set") public void setBiome( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 76cb60c64..e6a211a4b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -186,7 +186,10 @@ public class BrushCommands { @ArgFlag(name = 'm', desc = "Mask to limit blocks being considered", def = "") Mask mask ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); checkCommandArgument(minFreqDiff >= 0 && minFreqDiff <= 26, "minFreqDiff not in range 0 <= value <= 26"); if (mask != null && !(mask instanceof CachedMask)) { mask = new CachedMask(mask, false); @@ -212,7 +215,10 @@ public class BrushCommands { @Arg(desc = "fillRec", def = "1") int fillRec ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new ErodeBrush(erodefaces, erodeRec, fillFaces, fillRec), "worldedit.brush.erode").setSize(radius); } @@ -234,7 +240,10 @@ public class BrushCommands { @Arg(desc = "fillRec", def = "1") int fillRec ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new RaiseBrush(erodefaces, erodeRec, fillFaces, fillRec), "worldedit.brush.pull").setSize(radius); } @@ -252,7 +261,10 @@ public class BrushCommands { @Arg(name = "filled", desc = "Whether the circle should be filled", def = "false") boolean filled ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new CircleBrush(filled), "worldedit.brush.sphere").setSize(radius).setFill(fill); } @@ -276,7 +288,10 @@ public class BrushCommands { @Switch(name = 'd', desc = "Apply in depth first order") boolean depthFirst ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new RecurseBrush(depthFirst), "worldedit.brush.recursive").setSize(radius).setFill(fill) .setMask(new IdMask(editSession)); } @@ -299,7 +314,10 @@ public class BrushCommands { @Switch(name = 'f', desc = "Create a flat line") boolean flat ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new LineBrush(shell, select, flat), "worldedit.brush.line").setSize(radius).setFill(fill); } @@ -326,7 +344,10 @@ public class BrushCommands { Expression radius ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); player.print(Caption.of("fawe.worldedit.brush.brush.spline", (radius))); set(context, new SplineBrush(player), "worldedit.brush.spline").setSize(radius).setFill(fill); } @@ -379,7 +400,10 @@ public class BrushCommands { @Switch(name = 'd', desc = "sags the catenary toward the facing direction") boolean facingDirection ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new CatenaryBrush(shell, select, facingDirection, lengthFactor), "worldedit.brush.spline") .setSize(radius).setFill(fill); } @@ -411,7 +435,10 @@ public class BrushCommands { double quality ) throws WorldEditException { player.print(Caption.of("fawe.worldedit.brush.brush.spline", (radius))); - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new SurfaceSpline(tension, bias, continuity, quality), "surfacespline").setSize(radius) .setFill(fill); } @@ -435,10 +462,12 @@ public class BrushCommands { @Arg(desc = "double", def = "50") double amplitude ) throws WorldEditException { - double max = MathMan.max(radius.getX(), radius.getY(), radius.getZ()); - worldEdit.checkMaxBrushRadius(max); - Brush brush = - new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100, sphericity / 100); + double max = MathMan.max(radius.x(), radius.y(), radius.z()); + worldEdit.checkMaxBrushRadius( + max, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); + Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100, sphericity / 100); set(context, brush, "worldedit.brush.rock").setSize(max).setFill(fill); } @@ -459,7 +488,10 @@ public class BrushCommands { @Arg(desc = "Lines", def = "10") int count ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new ShatterBrush(count), "worldedit.brush.shatter").setSize(radius).setFill(fill) .setMask(new ExistingBlockMask(editSession)); } @@ -490,7 +522,10 @@ public class BrushCommands { boolean randomRotate ) throws WorldEditException, FileNotFoundException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); InputStream stream = getHeightmapStream(image); HeightBrush brush; int minY = player.getWorld().getMinY(); @@ -526,7 +561,10 @@ public class BrushCommands { URL url = new URL(imageURL); MainUtil.checkImageHost(url.toURI()); BufferedImage image = MainUtil.readImage(url); - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); if (yscale != 1) { ImageUtil.scaleAlpha(image, yscale); alpha = true; @@ -553,7 +591,10 @@ public class BrushCommands { @Arg(desc = "Expression", def = "5") Expression radius ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new SurfaceSphereBrush(), "worldedit.brush.surface").setFill(fill).setSize(radius); } @@ -578,7 +619,10 @@ public class BrushCommands { @Switch(name = 'o', desc = "Overlay the block") boolean overlay ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); Brush brush; if (overlay) { brush = new ScatterOverlayBrush((int) points, (int) distance); @@ -601,10 +645,10 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.populateschematic") public void scatterSchemBrush( Player player, InjectedValueAccess context, - @Arg(desc = "Mask") - Mask mask, @Arg(name = "clipboard", desc = "Clipboard uri") String clipboardStr, + @Arg(desc = "Mask of block to place on. Defaults to solid blocks.", def = "") + Mask mask, @Arg(desc = "Expression", def = "30") Expression radius, @Arg(desc = "double", def = "50") @@ -612,7 +656,10 @@ public class BrushCommands { @Switch(name = 'r', desc = "Apply random rotation") boolean rotate ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); try { MultiClipboardHolder clipboards = ClipboardFormats.loadAllFromInput(player, clipboardStr, null, true); @@ -651,7 +698,10 @@ public class BrushCommands { List patternLayers ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new LayerBrush(patternLayers.toArray(new Pattern[0])), "worldedit.brush.layer").setSize(radius); } @@ -678,7 +728,10 @@ public class BrushCommands { @Arg(desc = "boolean", def = "true") boolean solid ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new SplatterBrush((int) points, (int) recursion, solid), "worldedit.brush.splatter").setSize(radius) .setFill(fill); } @@ -711,7 +764,10 @@ public class BrushCommands { boolean print ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set( context, new ScatterCommand((int) points, (int) distance, StringMan.join(commandStr, " "), print), @@ -838,7 +894,10 @@ public class BrushCommands { InjectedValueAccess context ) throws WorldEditException, FileNotFoundException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); InputStream stream = getHeightmapStream(image); HeightBrush brush; int minY = player.getWorld().getMinY(); @@ -908,7 +967,10 @@ public class BrushCommands { @Switch(name = 'a', desc = "Apply auto view based rotation on paste") boolean autoRotate ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); player.print(Caption.of("fawe.worldedit.brush.brush.copy", (radius))); set(context, new CopyPastaBrush(player, session, randomRotate, autoRotate), "worldedit.brush.copy").setSize(radius); @@ -930,12 +992,15 @@ public class BrushCommands { Expression radius, @Arg(desc = "Command to run") List input, - @Switch(name = 'p', desc = "Show any printed output") - boolean print + @Switch(name = 'h', desc = "Hide any printed output") + boolean hide ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); String cmd = StringMan.join(input, " "); - set(context, new CommandBrush(cmd, print), "worldedit.brush.command").setSize(radius); + set(context, new CommandBrush(cmd, !hide), "worldedit.brush.command").setSize(radius); } @Command( @@ -1042,7 +1107,7 @@ public class BrushCommands { String permission ) throws WorldEditException { - WorldEdit.getInstance().checkMaxBrushRadius(radius); + WorldEdit.getInstance().checkMaxBrushRadius(radius, player); BrushTool tool = session.getBrushTool(player); tool.setSize(radius); tool.setFill(null); @@ -1197,7 +1262,10 @@ public class BrushCommands { @Switch(name = 'f', desc = "Create falling spheres instead") boolean falling ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); Brush brush; if (hollow) { brush = new HollowSphereBrush(); @@ -1244,8 +1312,14 @@ public class BrushCommands { @Switch(name = 'h', desc = "Create hollow cylinders instead") boolean hollow ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); - worldEdit.checkMaxBrushRadius(height); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); + worldEdit.checkMaxBrushRadius( + height, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); BrushSettings settings; if (hollow) { @@ -1293,9 +1367,18 @@ public class BrushCommands { BlockVector3 size = clipboard.getDimensions(); - worldEdit.checkMaxBrushRadius(size.getBlockX() / 2D - 1); - worldEdit.checkMaxBrushRadius(size.getBlockY() / 2D - 1); - worldEdit.checkMaxBrushRadius(size.getBlockZ() / 2D - 1); + worldEdit.checkMaxBrushRadius( + size.x() / 2D - 1, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); + worldEdit.checkMaxBrushRadius( + size.y() / 2D - 1, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); + worldEdit.checkMaxBrushRadius( + size.z() / 2D - 1, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set( context, @@ -1324,11 +1407,14 @@ public class BrushCommands { Mask mask, InjectedValueAccess context ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); //FAWE start FaweLimit limit = Settings.settings().getLimit(player); - iterations = Math.min(limit.MAX_ITERATIONS, iterations); + iterations = Math.min(limit.MAX_ITERATIONS.get(), iterations); //FAWE end set(context, new SmoothBrush(iterations, mask), "worldedit.brush.smooth").setSize(radius); @@ -1359,11 +1445,14 @@ public class BrushCommands { @ArgFlag(name = 'm', desc = "The mask of blocks to use for the heightmap") Mask mask, InjectedValueAccess context ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); //FAWE start FaweLimit limit = Settings.settings().getLimit(player); - iterations = Math.min(limit.MAX_ITERATIONS, iterations); + iterations = Math.min(limit.MAX_ITERATIONS.get(), iterations); //FAWE end set(context, new SnowSmoothBrush(iterations, snowBlockCount, mask), "worldedit.brush.snowsmooth").setSize(radius); @@ -1386,7 +1475,10 @@ public class BrushCommands { @Arg(desc = "The radius to extinguish", def = "5") Expression radius ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new SphereBrush(), "worldedit.brush.ex").setSize(radius).setFill(BlockTypes.AIR.getDefaultState()) .setMask(new SingleBlockTypeMask(editSession, BlockTypes.FIRE)); @@ -1405,7 +1497,10 @@ public class BrushCommands { @Switch(name = 'h', desc = "Affect blocks starting at max Y, rather than the target location Y + radius") boolean fromMaxY ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); set(context, new GravityBrush(fromMaxY), "worldedit.brush.gravity").setSize(radius); } @@ -1439,7 +1534,10 @@ public class BrushCommands { @Switch(name = 'w', desc = "Also kill water mobs") boolean killWater, InjectedValueAccess context ) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); + worldEdit.checkMaxBrushRadius( + radius, + context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) + ); CreatureButcher flags = new CreatureButcher(player); flags.or( @@ -1508,7 +1606,7 @@ public class BrushCommands { RegionFactory shape, String permission ) throws WorldEditException { - WorldEdit.getInstance().checkMaxBrushRadius(radius); + WorldEdit.getInstance().checkMaxBrushRadius(radius, player); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); tool.setSize(radius); tool.setFill(null); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index e39bbc641..a424682fe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -29,7 +29,6 @@ import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard; import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder; import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard; import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder; -import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.util.ImgurUtility; @@ -48,6 +47,8 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; +import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -71,6 +72,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionIntersection; @@ -149,10 +151,10 @@ public class ClipboardCommands { BlockVector3 max = region.getMaximumPoint(); long volume = - ((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min - .getZ() + 1); + ((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min + .z() + 1); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } session.setClipboard(null); @@ -183,10 +185,10 @@ public class ClipboardCommands { ) throws WorldEditException { BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); - long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min - .getZ() + 1)); + long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min + .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } session.setClipboard(null); @@ -256,13 +258,13 @@ public class ClipboardCommands { BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); - long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min - .getZ() + 1)); + long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min + .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } - if (volume >= limit.MAX_CHANGES) { + if (volume >= limit.MAX_CHANGES.get()) { throw FaweCache.MAX_CHANGES; } session.setClipboard(null); @@ -323,7 +325,7 @@ public class ClipboardCommands { } else { throw e; } - Fawe.instance().getClipboardExecutor().submit(actor.getUniqueId(), () -> { + Fawe.instance().submitUUIDKeyQueuedTask(actor.getUniqueId(), () -> { clipboard.close(); doc.getFile().delete(); }); @@ -339,7 +341,7 @@ public class ClipboardCommands { aliases = {"/download"}, desc = "Downloads your clipboard through the configured web interface" ) - @Deprecated + @Deprecated(forRemoval = true, since = "2.11.0") @CommandPermissions({"worldedit.clipboard.download"}) public void download( final Actor actor, @@ -401,10 +403,7 @@ public class ClipboardCommands { final Clipboard target; // If we have a transform, bake it into the copy if (!transform.isIdentity()) { - final FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform); - target = new BlockArrayClipboard(result.getTransformedRegion(), actor.getUniqueId()); - target.setOrigin(clipboard.getOrigin()); - Operations.completeLegacy(result.copyTo(target)); + target = clipboard.transform(transform); } else { target = clipboard; } @@ -440,6 +439,7 @@ public class ClipboardCommands { desc = "Place the clipboard's contents without applying transformations (e.g. rotate)" ) @CommandPermissions("worldedit.clipboard.place") + @SynchronousSettingExpected @Logging(PLACEMENT) public void place( Actor actor, World world, LocalSession session, final EditSession editSession, @@ -449,10 +449,14 @@ public class ClipboardCommands { boolean atOrigin, @Switch(name = 's', desc = "Select the region after pasting") boolean selectPasted, + @Switch(name = 'n', desc = "No paste, select only. (Implies -s)") + boolean onlySelect, @Switch(name = 'e', desc = "Paste entities if available") boolean pasteEntities, @Switch(name = 'b', desc = "Paste biomes if available") - boolean pasteBiomes + boolean pasteBiomes, + @Switch(name = 'x', desc = "Remove existing entities in the affected region") + boolean removeEntities ) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); final Clipboard clipboard = holder.getClipboard(); @@ -460,22 +464,33 @@ public class ClipboardCommands { final BlockVector3 to = atOrigin ? origin : session.getPlacementPosition(actor); checkPaste(actor, editSession, to, holder, clipboard); - clipboard.paste(editSession, to, !ignoreAirBlocks, pasteEntities, pasteBiomes); + if (!onlySelect) { + clipboard.paste(editSession, to, !ignoreAirBlocks, pasteEntities, pasteBiomes); + } Region region = clipboard.getRegion().clone(); - if (selectPasted) { + if (selectPasted || onlySelect || removeEntities) { BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); BlockVector3 realTo = to.add(holder.getTransform().apply(clipboardOffset.toVector3()).toBlockPoint()); BlockVector3 max = realTo.add(holder .getTransform() .apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()) .toBlockPoint()); - RegionSelector selector = new CuboidRegionSelector(world, realTo, max); - session.setRegionSelector(world, selector); - selector.learnChanges(); - selector.explainRegionAdjust(actor, session); + if (removeEntities) { + editSession.getEntities(new CuboidRegion(realTo, max)).forEach(Entity::remove); + } + if (selectPasted || onlySelect) { + RegionSelector selector = new CuboidRegionSelector(world, realTo, max); + session.setRegionSelector(world, selector); + selector.learnChanges(); + selector.explainRegionAdjust(actor, session); + } + } + if (onlySelect) { + actor.print(Caption.of("worldedit.paste.selected")); + } else { + actor.print(Caption.of("fawe.worldedit.paste.command.paste", to)); } - actor.print(Caption.of("fawe.worldedit.paste.command.paste", to)); if (!actor.hasPermission("fawe.tips")) { actor.print(Caption.of("fawe.tips.tip.copypaste")); @@ -489,6 +504,7 @@ public class ClipboardCommands { desc = "Paste the clipboard's contents" ) @CommandPermissions("worldedit.clipboard.paste") + @SynchronousSettingExpected @Logging(PLACEMENT) public void paste( Actor actor, World world, LocalSession session, EditSession editSession, @@ -506,14 +522,19 @@ public class ClipboardCommands { boolean pasteBiomes, @ArgFlag(name = 'm', desc = "Only paste blocks matching this mask") @ClipboardMask - Mask sourceMask + Mask sourceMask, + //FAWE start - entity removal + @Switch(name = 'x', desc = "Remove existing entities in the affected region") + boolean removeEntities + //FAWE end + ) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); //FAWE start - use place if (holder.getTransform().isIdentity() && sourceMask == null) { - place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted, - pasteEntities, pasteBiomes + place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted, onlySelect, + pasteEntities, pasteBiomes, removeEntities ); return; } @@ -540,21 +561,29 @@ public class ClipboardCommands { messages.addAll(Lists.newArrayList(operation.getStatusMessages())); } - if (selectPasted || onlySelect) { + if (selectPasted || onlySelect || removeEntities) { BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); Vector3 realTo = to.toVector3().add(holder.getTransform().apply(clipboardOffset.toVector3())); Vector3 max = realTo.add(holder .getTransform() .apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3())); - final CuboidRegionSelector selector; - if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) { - selector = new ExtendingCuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); - } else { - selector = new CuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); + + // FAWE start - entity remova;l + if (removeEntities) { + editSession.getEntities(new CuboidRegion(realTo.toBlockPoint(), max.toBlockPoint())).forEach(Entity::remove); + } + if (selectPasted || onlySelect) { + //FAWE end + final CuboidRegionSelector selector; + if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) { + selector = new ExtendingCuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); + } else { + selector = new CuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); + } + session.setRegionSelector(world, selector); + selector.learnChanges(); + selector.explainRegionAdjust(actor, session); } - session.setRegionSelector(world, selector); - selector.learnChanges(); - selector.explainRegionAdjust(actor, session); } if (onlySelect) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 0cf5b1a78..865e6f937 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -349,7 +349,7 @@ public class GeneralCommands { if (world == null) { actor.print(Caption.of("worldedit.world.remove")); } else { - actor.print(Caption.of("worldedit.world.set", TextComponent.of(world.getId()))); + actor.print(Caption.of("worldedit.world.set", TextComponent.of(world.id()))); } } @@ -510,6 +510,7 @@ public class GeneralCommands { parserContext.setWorld(worldArg); parserContext.setSession(session); parserContext.setExtent(editSession); + parserContext.setTryLegacy(actor.getLimit().ALLOW_LEGACY); Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext); util = TextureUtil.fromMask(mask); } @@ -641,7 +642,7 @@ public class GeneralCommands { if (itemsOnly && searchType.hasBlockType()) { continue; } - final String id = searchType.getId(); + final String id = searchType.id(); if (id.contains(idMatch)) { Component name = searchType.getRichName(); results.put(id, TextComponent.builder() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index dbd698b24..f2a3c80ed 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -38,6 +38,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.mask.Mask; @@ -104,6 +105,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hcyl( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -130,9 +132,9 @@ public class GenerationCommands { return 0; } } - worldEdit.checkMaxRadius(radiusX); - worldEdit.checkMaxRadius(radiusZ); - worldEdit.checkMaxRadius(height); + worldEdit.checkMaxRadius(radiusX, actor); + worldEdit.checkMaxRadius(radiusZ, actor); + worldEdit.checkMaxRadius(height, actor); if (thickness > radiusX || thickness > radiusZ) { actor.print(Caption.of("worldedit.hcyl.thickness-too-large")); @@ -152,6 +154,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) + @SynchronousSettingExpected public int cyl( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -178,12 +181,15 @@ public class GenerationCommands { } } - worldEdit.checkMaxRadius(radiusX); - worldEdit.checkMaxRadius(radiusZ); - worldEdit.checkMaxRadius(height); + worldEdit.checkMaxRadius(radiusX, actor); + worldEdit.checkMaxRadius(radiusZ, actor); + worldEdit.checkMaxRadius(height, actor); BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow); + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } actor.print(Caption.of("worldedit.cyl.created", TextComponent.of(affected))); return affected; } @@ -194,6 +200,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cone") @Logging(PLACEMENT) + @SynchronousSettingExpected public int cone(Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") Pattern pattern, @@ -221,12 +228,15 @@ public class GenerationCommands { } } - worldEdit.checkMaxRadius(radiusX); - worldEdit.checkMaxRadius(radiusZ); - worldEdit.checkMaxRadius(height); + worldEdit.checkMaxRadius(radiusX, actor); + worldEdit.checkMaxRadius(radiusZ, actor); + worldEdit.checkMaxRadius(height, actor); BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makeCone(pos, pattern, radiusX, radiusZ, height, !hollow, thickness); + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } actor.printInfo(Caption.of("worldedit.cone.created", TextComponent.of(affected))); return affected; } @@ -237,6 +247,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hsphere( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -256,6 +267,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) + @SynchronousSettingExpected public int sphere( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -284,16 +296,16 @@ public class GenerationCommands { } } - worldEdit.checkMaxRadius(radiusX); - worldEdit.checkMaxRadius(radiusY); - worldEdit.checkMaxRadius(radiusZ); + worldEdit.checkMaxRadius(radiusX, actor); + worldEdit.checkMaxRadius(radiusY, actor); + worldEdit.checkMaxRadius(radiusZ, actor); BlockVector3 pos = session.getPlacementPosition(actor); if (raised) { pos = pos.add(0, (int) radiusY, 0); } int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); @@ -307,6 +319,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.forest") @Logging(POSITION) + @SynchronousSettingExpected public int forestGen( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The size of the forest, in blocks", def = "10") @@ -317,7 +330,7 @@ public class GenerationCommands { double density ) throws WorldEditException { checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100"); - worldEdit.checkMaxRadius(size); + worldEdit.checkMaxRadius(size, actor); density /= 100; int affected = editSession.makeForest(session.getPlacementPosition(actor), size, density, type); actor.print(Caption.of("worldedit.forestgen.created", TextComponent.of(affected))); @@ -331,6 +344,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pumpkins") @Logging(POSITION) + @SynchronousSettingExpected public int pumpkins( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The size of the patch", def = "10") @@ -339,7 +353,7 @@ public class GenerationCommands { double density ) throws WorldEditException { checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100"); - worldEdit.checkMaxRadius(size); + worldEdit.checkMaxRadius(size, actor); int affected = editSession.makePumpkinPatches(session.getPlacementPosition(actor), size, density); actor.print(Caption.of("worldedit.pumpkins.created", TextComponent.of(affected))); return affected; @@ -351,6 +365,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hollowPyramid( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to set") @@ -367,6 +382,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) + @SynchronousSettingExpected public int pyramid( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to set") @@ -376,10 +392,10 @@ public class GenerationCommands { @Switch(name = 'h', desc = "Make a hollow pyramid") boolean hollow ) throws WorldEditException { - worldEdit.checkMaxRadius(size); + worldEdit.checkMaxRadius(size, actor); BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makePyramid(pos, pattern, size, !hollow); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.pyramid.created", TextComponent.of(affected))); @@ -394,6 +410,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.shape") @Logging(ALL) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int generate( Actor actor, LocalSession session, EditSession editSession, @@ -434,13 +451,13 @@ public class GenerationCommands { zero = max.add(min).multiply(0.5); unit = max.subtract(zero); - if (unit.getX() == 0) { + if (unit.x() == 0) { unit = unit.withX(1.0); } - if (unit.getY() == 0) { + if (unit.y() == 0) { unit = unit.withY(1.0); } - if (unit.getZ() == 0) { + if (unit.z() == 0) { unit = unit.withZ(1.0); } } @@ -457,7 +474,7 @@ public class GenerationCommands { hollow, session.getTimeout() ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.generate.created", TextComponent.of(affected))); @@ -480,6 +497,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.shape.biome") @Logging(ALL) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int generateBiome( Actor actor, LocalSession session, EditSession editSession, @@ -520,13 +538,13 @@ public class GenerationCommands { zero = max.add(min).multiply(0.5); unit = max.subtract(zero); - if (unit.getX() == 0) { + if (unit.x() == 0) { unit = unit.withX(1.0); } - if (unit.getY() == 0) { + if (unit.y() == 0) { unit = unit.withY(1.0); } - if (unit.getZ() == 0) { + if (unit.z() == 0) { unit = unit.withZ(1.0); } } @@ -558,6 +576,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.caves") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void caves( Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @@ -596,6 +615,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.ore") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void ores( Actor actor, @@ -615,6 +635,7 @@ public class GenerationCommands { desc = "Generate an image" ) @CommandPermissions("worldedit.generation.image") + @SynchronousSettingExpected @Logging(PLACEMENT) public void image( Actor actor, @@ -630,7 +651,7 @@ public class GenerationCommands { MainUtil.checkImageHost(url.toURI()); if (dimensions != null) { checkCommandArgument( - (long) dimensions.getX() * dimensions.getZ() <= Settings.settings().WEB.MAX_IMAGE_SIZE, + (long) dimensions.x() * dimensions.z() <= Settings.settings().WEB.MAX_IMAGE_SIZE, Caption.of("fawe.error.image-dimensions", Settings.settings().WEB.MAX_IMAGE_SIZE) ); } @@ -638,7 +659,7 @@ public class GenerationCommands { Future future = executor.submit(() -> { BufferedImage image = MainUtil.readImage(url); if (dimensions != null) { - image = ImageUtil.getScaledInstance(image, dimensions.getBlockX(), dimensions.getBlockZ(), + image = ImageUtil.getScaledInstance(image, dimensions.x(), dimensions.z(), RenderingHints.VALUE_INTERPOLATION_BILINEAR, false ); } @@ -662,8 +683,8 @@ public class GenerationCommands { CuboidRegion region = new CuboidRegion(pos1, pos2); final BufferedImage finalImage = image; RegionVisitor visitor = new RegionVisitor(region, pos -> { - int x = pos.getBlockX() - pos1.getBlockX(); - int z = pos.getBlockZ() - pos1.getBlockZ(); + int x = pos.x() - pos1.x(); + int z = pos.z() - pos1.z(); int color = finalImage.getRGB(x, z); BlockType block = tu.getNearestBlock(color); if (block != null) { @@ -679,6 +700,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.ore") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void ore( Actor actor, @@ -713,8 +735,9 @@ public class GenerationCommands { desc = "Creates a distorted sphere" ) @Logging(PLACEMENT) + @SynchronousSettingExpected @CommandPermissions("worldedit.generation.blob") - public int blobBrush( + public int blob( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "Pattern") Pattern pattern, @@ -729,8 +752,8 @@ public class GenerationCommands { @Arg(desc = "double", def = "50") double amplitude ) throws WorldEditException { - double max = MathMan.max(radius.getX(), radius.getY(), radius.getZ()); - worldEdit.checkMaxRadius(max); + double max = MathMan.max(radius.x(), radius.y(), radius.z()); + worldEdit.checkMaxRadius(max, actor); BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makeBlob( pos, @@ -741,7 +764,7 @@ public class GenerationCommands { radius.divide(max), sphericity / 100 ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index d1a647587..ba736e45e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.annotation.Confirm; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -61,6 +62,7 @@ public class HistoryCommands { desc = "Undoes the last action (from history)" ) @CommandPermissions({"worldedit.history.undo", "worldedit.history.undo.self"}) + @SynchronousSettingExpected public void undo( Actor actor, LocalSession session, @Confirm(Confirm.Processor.LIMIT) @Arg(desc = "Number of undoes to perform", def = "1") @@ -108,6 +110,7 @@ public class HistoryCommands { desc = "Redoes the last action (from history)" ) @CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"}) + @SynchronousSettingExpected public void redo( Actor actor, LocalSession session, @Confirm(Confirm.Processor.LIMIT) @Arg(desc = "Number of redoes to perform", def = "1") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java index 452d5084c..38fc18415 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java @@ -18,7 +18,6 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; -import com.sk89q.worldedit.command.util.annotation.AllowedRegion; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Time; import com.sk89q.worldedit.entity.Player; @@ -26,7 +25,6 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Identifiable; @@ -80,7 +78,6 @@ public class HistorySubCommands { @Confirm public synchronized void rerun( Player player, World world, RollbackDatabase database, - @AllowedRegion Region[] allowedRegions, @ArgFlag(name = 'u', desc = "String user", def = "me") UUID other, @ArgFlag(name = 'r', def = "0", desc = "radius") @@ -90,7 +87,7 @@ public class HistorySubCommands { @Time long timeDiff ) throws WorldEditException { - rollback(player, world, database, allowedRegions, other, radius, timeDiff, true); + rollback(player, world, database, other, radius, timeDiff, true); } @Command( @@ -102,7 +99,6 @@ public class HistorySubCommands { @Confirm public synchronized void rollback( Player player, World world, RollbackDatabase database, - @AllowedRegion Region[] allowedRegions, @ArgFlag(name = 'u', desc = "String user", def = "") UUID other, @ArgFlag(name = 'r', def = "0", desc = "radius") @@ -149,9 +145,9 @@ public class HistorySubCommands { count++; RollbackOptimizedHistory edit = supplier.get(); if (restore) { - edit.redo(player, allowedRegions); + edit.redo(player); } else { - edit.undo(player, allowedRegions); + edit.undo(player); } String path = edit.getWorld().getName() + "/" + finalOther + "-" + edit.getIndex(); player.print(Caption.of("fawe.worldedit.rollback.rollback.element", path)); @@ -201,8 +197,7 @@ public class HistorySubCommands { .at(summary.maxX, world.getMaxY(), summary.maxZ) ); rollback.setTime(historyFile.lastModified()); - RollbackDatabase db = DBHandler.IMP - .getDatabase(world); + RollbackDatabase db = DBHandler.dbHandler().getDatabase(world); db.logEdit(rollback); actor.print(TextComponent.of("Logging: " + historyFile)); } @@ -246,17 +241,17 @@ public class HistorySubCommands { BlockVector3 pos1 = edit.getMinimumPoint(); BlockVector3 pos2 = edit.getMaximumPoint(); - double distanceX = Math.min(Math.abs(pos1.getX() - origin.getX()), Math.abs(pos2.getX() - origin.getX())); - double distanceZ = Math.min(Math.abs(pos1.getZ() - origin.getZ()), Math.abs(pos2.getZ() - origin.getZ())); + double distanceX = Math.min(Math.abs(pos1.x() - origin.x()), Math.abs(pos2.x() - origin.x())); + double distanceZ = Math.min(Math.abs(pos1.z() - origin.z()), Math.abs(pos2.z() - origin.z())); int distance = (int) Math.sqrt(distanceX * distanceX + distanceZ * distanceZ); - BlockVector2 dirVec = BlockVector2.at(edit.getOriginX() - origin.getX(), edit.getOriginZ() - origin.getZ()); + BlockVector2 dirVec = BlockVector2.at(edit.getOriginX() - origin.x(), edit.getOriginZ() - origin.z()); Direction direction = Direction.findClosest(dirVec.toVector3(), Direction.Flag.ALL); long seconds = (System.currentTimeMillis() - edit.getBDFile().lastModified()) / 1000; String timeStr = MainUtil.secToTime(seconds); - int size = edit.size(); + long size = edit.longSize(); boolean biomes = edit.getBioFile().exists(); boolean createdEnts = edit.getEnttFile().exists(); boolean removedEnts = edit.getEntfFile().exists(); @@ -327,20 +322,20 @@ public class HistorySubCommands { BlockVector3 pos1 = rollback.getMinimumPoint(); BlockVector3 pos2 = rollback.getMaximumPoint(); - double distanceX = Math.min(Math.abs(pos1.getX() - origin.getX()), Math.abs(pos2.getX() - origin.getX())); - double distanceZ = Math.min(Math.abs(pos1.getZ() - origin.getZ()), Math.abs(pos2.getZ() - origin.getZ())); + double distanceX = Math.min(Math.abs(pos1.x() - origin.x()), Math.abs(pos2.x() - origin.x())); + double distanceZ = Math.min(Math.abs(pos1.z() - origin.z()), Math.abs(pos2.z() - origin.z())); int distance = (int) Math.sqrt(distanceX * distanceX + distanceZ * distanceZ); BlockVector2 dirVec = BlockVector2.at( - rollback.getOriginX() - origin.getX(), - rollback.getOriginZ() - origin.getZ() + rollback.getOriginX() - origin.x(), + rollback.getOriginZ() - origin.z() ); Direction direction = Direction.findClosest(dirVec.toVector3(), Direction.Flag.ALL); long seconds = (System.currentTimeMillis() - rollback.getBDFile().lastModified()) / 1000; String timeStr = MainUtil.secToTime(seconds); - int size = edit.size(); + long size = edit.longSize(); TranslatableComponent elem = Caption.of( "fawe.worldedit.history.find.element", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index a72cba4b3..2847542a5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.command; import com.fastasyncworldedit.core.FaweAPI; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.util.MaskTraverser; @@ -34,6 +35,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.GroundFunction; @@ -224,6 +226,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.region.line") @Logging(REGION) + @SynchronousSettingExpected public int line( Actor actor, EditSession editSession, @Selection Region region, @@ -256,6 +259,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.curve") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected public int curve( Actor actor, EditSession editSession, @Selection Region region, @@ -314,6 +318,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.overlay") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement public int overlay( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "The pattern of blocks to overlay") @@ -332,6 +337,7 @@ public class RegionCommands { @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement public void lay( Actor actor, EditSession editSession, @@ -350,8 +356,8 @@ public class RegionCommands { int affected = 0; while (iter.hasNext()) { BlockVector2 pos = iter.next(); - int x = pos.getBlockX(); - int z = pos.getBlockZ(); + int x = pos.x(); + int z = pos.z(); //FAWE start - world min/maxY y = editSession.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); //FAWE end @@ -368,6 +374,7 @@ public class RegionCommands { ) @Logging(REGION) @CommandPermissions("worldedit.region.center") + @SynchronousSettingExpected public int center( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "The pattern of blocks to set") @@ -385,6 +392,8 @@ public class RegionCommands { @CommandPermissions("worldedit.region.naturalize") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement + @Preload(Preload.PreloadCheck.PRELOAD) public int naturalize(Actor actor, EditSession editSession, @Selection Region region) throws WorldEditException { int affected = editSession.naturalizeCuboidBlocks(region); actor.print(Caption.of("worldedit.naturalize.naturalized", TextComponent.of(affected))); @@ -436,6 +445,7 @@ public class RegionCommands { @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected public int smooth( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "# of iterations to perform", def = "1") @@ -448,10 +458,10 @@ public class RegionCommands { //FAWE end BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); - long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min - .getZ() + 1)); + long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min + .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } int affected; @@ -509,6 +519,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.snowsmooth") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int snowSmooth( Actor actor, EditSession editSession, @Selection Region region, @@ -535,6 +546,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.move") @Logging(ORIENTATION_REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int move( Actor actor, World world, EditSession editSession, LocalSession session, @@ -582,7 +594,7 @@ public class RegionCommands { session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).explainRegionAdjust(actor, session); } catch (RegionOperationException e) { - actor.printError(TextComponent.of(e.getMessage())); + actor.printError(e.getRichMessage()); } } @@ -598,6 +610,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.fall") @Logging(ORIENTATION_REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void fall( Actor actor, EditSession editSession, @@ -617,6 +630,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.region.stack") @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Logging(ORIENTATION_REGION) public int stack( Actor actor, World world, EditSession editSession, LocalSession session, @@ -626,7 +640,7 @@ public class RegionCommands { int count, @Arg(desc = "How far to move the contents each stack", def = Offset.FORWARD) @Offset - BlockVector3 direction, + BlockVector3 offset, @Switch(name = 's', desc = "Shift the selection to the last stacked copy") boolean moveSelection, @Switch(name = 'a', desc = "Ignore air blocks") @@ -635,6 +649,8 @@ public class RegionCommands { boolean copyEntities, @Switch(name = 'b', desc = "Also copy biomes") boolean copyBiomes, + @Switch(name = 'r', desc = "Use block units") + boolean blockUnits, @ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air") Mask mask ) throws WorldEditException { @@ -654,19 +670,24 @@ public class RegionCommands { combinedMask = mask; } - int affected = editSession.stackCuboidRegion(region, direction, count, copyEntities, copyBiomes, combinedMask); + int affected; + if (blockUnits) { + affected = editSession.stackRegionBlockUnits(region, offset, count, copyEntities, copyBiomes, combinedMask); + } else { + affected = editSession.stackCuboidRegion(region, offset, count, copyEntities, copyBiomes, combinedMask); + } if (moveSelection) { try { final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); - - final BlockVector3 shiftVector = direction.multiply(size).multiply(count); + final BlockVector3 shiftSize = blockUnits ? offset : offset.multiply(size); + final BlockVector3 shiftVector = shiftSize.multiply(count); region.shift(shiftVector); session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).explainRegionAdjust(actor, session); } catch (RegionOperationException e) { - actor.printError(TextComponent.of(e.getMessage())); + actor.printError(e.getRichMessage()); } } @@ -682,6 +703,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.regen") @Logging(REGION) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) void regenerate( Actor actor, World world, LocalSession session, EditSession editSession, @@ -715,6 +737,9 @@ public class RegionCommands { session.setSourceMask(mask); //FAWE end } + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } if (success) { actor.print(Caption.of("worldedit.regen.regenerated")); } else { @@ -733,6 +758,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.deform") @Logging(ALL) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int deform( Actor actor, LocalSession session, EditSession editSession, @@ -768,13 +794,13 @@ public class RegionCommands { zero = max.add(min).divide(2); unit = max.subtract(zero); - if (unit.getX() == 0) { + if (unit.x() == 0) { unit = unit.withX(1.0); } - if (unit.getY() == 0) { + if (unit.y() == 0) { unit = unit.withY(1.0); } - if (unit.getZ() == 0) { + if (unit.z() == 0) { unit = unit.withZ(1.0); } } @@ -788,7 +814,7 @@ public class RegionCommands { String.join(" ", expression), session.getTimeout() ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.deform.deformed", TextComponent.of(affected))); @@ -810,6 +836,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.hollow") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int hollow( Actor actor, EditSession editSession, @@ -844,6 +871,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.forest") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int forest( Actor actor, EditSession editSession, @Selection Region region, @@ -865,6 +893,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.flora") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int flora( Actor actor, EditSession editSession, @Selection Region region, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index c677734ef..1b818786a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -37,13 +37,13 @@ import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; -import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestination; +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareMetadata; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; @@ -69,17 +69,18 @@ import org.enginehub.piston.exception.StopExecutionException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.Closeable; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -91,6 +92,7 @@ import java.util.Objects; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Pattern; @@ -313,9 +315,9 @@ public class SchematicCommands { Actor actor, LocalSession session, @Arg(desc = "File name.") String filename, - @Arg(desc = "Format name.", def = "fast") + //FAWE start - use format-name, random rotation + @Arg(desc = "Format name.", def = "") String formatName, - //FAWE start - random rotation @Switch(name = 'r', desc = "Apply random rotation to the clipboard") boolean randomRotate //FAWE end @@ -324,8 +326,13 @@ public class SchematicCommands { //FAWE start ClipboardFormat format; - InputStream in = null; - try { + InputStream in; + // if format is set explicitly, do not look up by extension! + boolean noExplicitFormat = formatName == null; + if (noExplicitFormat) { + formatName = "fast"; + } + try(final Closer closer = Closer.create()) { URI uri; if (formatName.startsWith("url:")) { String t = filename; @@ -339,17 +346,37 @@ public class SchematicCommands { } UUID uuid = UUID.fromString(filename.substring(4)); URL webUrl = new URL(Settings.settings().WEB.URL); - format = ClipboardFormats.findByAlias(formatName); + if ((format = ClipboardFormats.findByAlias(formatName)) == null) { + actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); + return; + } + // The interface requires the correct schematic extension - otherwise it can't be downloaded + // So it basically only supports .schem files (sponge v2 + v3) - or the correct extensions is specified manually + // Sadly it's not really an API endpoint but spits out the HTML source of the uploader - so no real handling + // can happen URL url = new URL(webUrl, "uploads/" + uuid + "." + format.getPrimaryFileExtension()); - ReadableByteChannel byteChannel = Channels.newChannel(url.openStream()); - in = Channels.newInputStream(byteChannel); - uri = url.toURI(); + final Path temp = Files.createTempFile("faweremoteschem", null); + final File tempFile = temp.toFile(); + // delete temporary file when we're done + closer.register((Closeable) () -> Files.deleteIfExists(temp)); + // write schematic into temporary file + try (final InputStream urlIn = new BufferedInputStream(url.openStream()); + final OutputStream tempOut = new BufferedOutputStream(new FileOutputStream(tempFile))) { + urlIn.transferTo(tempOut); + } + // No format is specified -> try or fail + if (noExplicitFormat && (format = ClipboardFormats.findByFile(tempFile)) == null) { + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", TextComponent.of(filename))); + return; + } + in = new FileInputStream(tempFile); + uri = temp.toUri(); } else { File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile(); File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(saveDir, actor.getUniqueId().toString()) : saveDir; File file; if (filename.startsWith("#")) { - format = ClipboardFormats.findByAlias(formatName); + format = noExplicitFormat ? null : ClipboardFormats.findByAlias(formatName); String[] extensions; if (format != null) { extensions = format.getFileExtensions().toArray(new String[0]); @@ -369,11 +396,13 @@ public class SchematicCommands { actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.load.other")); return; } - if (filename.matches(".*\\.[\\w].*")) { - format = ClipboardFormats - .findByExtension(filename.substring(filename.lastIndexOf('.') + 1)); - } else { + if (!noExplicitFormat) { format = ClipboardFormats.findByAlias(formatName); + } else if (filename.matches(".*\\.\\w.*")) { + format = ClipboardFormats + .findByExplicitExtension(filename.substring(filename.lastIndexOf('.') + 1)); + } else { + format = null; } file = MainUtil.resolve(dir, filename, format, false); } @@ -392,13 +421,18 @@ public class SchematicCommands { if (format == null) { format = ClipboardFormats.findByFile(file); if (format == null) { - actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); + if (noExplicitFormat) { + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", TextComponent.of(file.getName()))); + } else { + actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); + } return; } } in = new FileInputStream(file); uri = file.toURI(); } + closer.register(in); format.hold(actor, uri, in); if (randomRotate) { AffineTransform transform = new AffineTransform(); @@ -409,16 +443,18 @@ public class SchematicCommands { actor.print(Caption.of("fawe.worldedit.schematic.schematic.loaded", filename)); } catch (IllegalArgumentException e) { actor.print(Caption.of("worldedit.schematic.unknown-filename", TextComponent.of(filename))); - } catch (URISyntaxException | IOException e) { + } catch (EOFException e) { + // EOFException is extending IOException - but the IOException error is too generic. + // EOF mostly occurs when there was unexpected content in the schematic - due to the wrong reader (= version) + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", + TextComponent.of(e.getMessage() != null ? e.getMessage() : "EOFException"))); // often null... + LOGGER.error("Error loading a schematic", e); + } catch (IOException e) { actor.print(Caption.of("worldedit.schematic.file-not-exist", TextComponent.of(Objects.toString(e.getMessage())))); LOGGER.warn("Failed to load a saved clipboard", e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ignored) { - } - } + } catch (Exception e) { + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", TextComponent.of(e.getMessage()))); + LOGGER.error("Error loading a schematic", e); } //FAWE end } @@ -432,8 +468,8 @@ public class SchematicCommands { Actor actor, LocalSession session, @Arg(desc = "File name.") String filename, - @Arg(desc = "Format name.", def = "fast") - String formatName, + @Arg(desc = "Format name.", def = "fast") //FAWE: def: sponge -> fast + ClipboardFormat format, @Switch(name = 'f', desc = "Overwrite an existing file.") boolean allowOverwrite, //FAWE start @@ -461,12 +497,6 @@ public class SchematicCommands { dir = new File(dir, actor.getUniqueId().toString()); } - ClipboardFormat format = ClipboardFormats.findByAlias(formatName); - if (format == null) { - actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); - return; - } - boolean other = false; if (filename.contains("../")) { other = true; @@ -531,6 +561,105 @@ public class SchematicCommands { .buildAndExec(worldEdit.getExecutorService()); } + @Command( + name = "share", + desc = "Share your clipboard as a schematic online" + ) + @CommandPermissions({ "worldedit.clipboard.share", "worldedit.schematic.share" }) + public void share(Actor actor, LocalSession session, + @Arg(desc = "Schematic name. Defaults to name-millis", def = "") + String schematicName, + @Arg(desc = "Share location", def = "arkitektonika") //FAWE: def: ehpaste -> arkitektonika + ClipboardShareDestination destination, + @Arg(desc = "Format name", def = "fast") //FAWE: def: sponge -> fast + ClipboardFormat format) throws WorldEditException { + if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) { + actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version")); + return; + } + + if (format == null) { + format = destination.getDefaultFormat(); + } + + if (!destination.supportsFormat(format)) { + actor.printError(Caption.of( //FAWE: TranslatableComponent -> Caption + "worldedit.schematic.share.unsupported-format", + TextComponent.of(destination.getName()), + TextComponent.of(format.getName()) + )); + return; + } + + ClipboardHolder holder = session.getClipboard(); + + SchematicShareTask task = new SchematicShareTask(actor, holder, destination, format, schematicName); + AsyncCommandBuilder.wrap(task, actor) + .registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic") + .setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving")) + .setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving")) + .onSuccess("Shared", (consumer -> consumer.accept(actor))) + .onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter()) + .buildAndExec(worldEdit.getExecutorService()); + } + + @Command( + name = "delete", + aliases = {"d"}, + desc = "Delete a saved schematic" + ) + @CommandPermissions("worldedit.schematic.delete") + public void delete( + Actor actor, LocalSession session, + @Arg(desc = "File name.") + String filename + ) throws WorldEditException, IOException { + LocalConfiguration config = worldEdit.getConfiguration(); + //FAWE start + File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile(); + File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working; + List files = new ArrayList<>(); + + if (filename.equalsIgnoreCase("*")) { + files.addAll(getFiles(session.getClipboard())); + } else { + File f = MainUtil.resolveRelative(new File(dir, filename)); + files.add(f); + } + + if (files.isEmpty()) { + actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename))); + return; + } + for (File f : files) { + if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) { + actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename))); + continue; + } + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission( + "worldedit.schematic.delete.other")) { + actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.delete.other")); + continue; + } + if (!deleteFile(f)) { + actor.print(Caption.of("worldedit.schematic.delete.failed", TextComponent.of(filename))); + continue; + } + actor.print(Caption.of("worldedit.schematic.delete.deleted", filename)); + } + //FAWE end + } + + //FAWE start + private boolean deleteFile(File file) { + if (file.delete()) { + new File(file.getParentFile(), "." + file.getName() + ".cached").delete(); + return true; + } + return false; + } + //FAWE end + @Command( name = "formats", aliases = {"listformats", "f"}, @@ -695,10 +824,10 @@ public class SchematicCommands { String headerBytesElem = String.format("%.1fkb", totalBytes / 1000.0); - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1) { headerBytesElem += String.format( " / %dkb", - Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT + actor.getLimit().SCHEM_FILE_SIZE_LIMIT ); } @@ -715,68 +844,11 @@ public class SchematicCommands { } - @Command( - name = "delete", - aliases = {"d"}, - desc = "Delete a saved schematic" - ) - @CommandPermissions("worldedit.schematic.delete") - public void delete( - Actor actor, LocalSession session, - @Arg(desc = "File name.") - String filename - ) throws WorldEditException, IOException { - LocalConfiguration config = worldEdit.getConfiguration(); - File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile(); - //FAWE start - File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working; - List files = new ArrayList<>(); - - if (filename.equalsIgnoreCase("*")) { - files.addAll(getFiles(session.getClipboard())); - } else { - File f = MainUtil.resolveRelative(new File(dir, filename)); - files.add(f); - } - - if (files.isEmpty()) { - actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename))); - return; - } - for (File f : files) { - if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) { - actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename))); - continue; - } - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission( - "worldedit.schematic.delete.other")) { - actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.delete.other")); - continue; - } - if (!deleteFile(f)) { - actor.print(Caption.of("worldedit.schematic.delete.failed", TextComponent.of(filename))); - continue; - } - actor.print(Caption.of("worldedit.schematic.delete.deleted", filename)); - } - //FAWE end - } - - //FAWE start - private boolean deleteFile(File file) { - if (file.delete()) { - new File(file.getParentFile(), "." + file.getName() + ".cached").delete(); - return true; - } - return false; - } - //FAWE end - private static class SchematicLoadTask implements Callable { private final Actor actor; - private final ClipboardFormat format; private final File file; + private final ClipboardFormat format; SchematicLoadTask(Actor actor, File file, ClipboardFormat format) { this.actor = actor; @@ -799,14 +871,40 @@ public class SchematicCommands { } - private static class SchematicSaveTask implements Callable { + private abstract static class SchematicOutputTask implements Callable { + protected final Actor actor; + protected final ClipboardFormat format; + protected final ClipboardHolder holder; + SchematicOutputTask( + Actor actor, + ClipboardFormat format, + ClipboardHolder holder + ) { + this.actor = actor; + this.format = format; + this.holder = holder; + } + + protected void writeToOutputStream(OutputStream outputStream) throws IOException, WorldEditException { + Clipboard clipboard = holder.getClipboard(); + Transform transform = holder.getTransform(); + Clipboard target = clipboard.transform(transform); + + try (Closer closer = Closer.create()) { + OutputStream stream = closer.register(outputStream); + BufferedOutputStream bos = closer.register(new BufferedOutputStream(stream)); + ClipboardWriter writer = closer.register(format.getWriter(bos)); + writer.write(target); + } + } + } + + private static class SchematicSaveTask extends SchematicOutputTask { private final Actor actor; - private final ClipboardFormat format; - private final ClipboardHolder holder; + private File file; //FAWE: un-finalize private final boolean overwrite; - private final File rootDir; - private File file; + private final File rootDir; //FAWE: add root-dir SchematicSaveTask( Actor actor, @@ -816,12 +914,11 @@ public class SchematicCommands { ClipboardHolder holder, boolean overwrite ) { + super(actor, format, holder); this.actor = actor; this.file = file; - this.rootDir = rootDir; - this.format = format; - this.holder = holder; this.overwrite = overwrite; + this.rootDir = rootDir; //FAWE: add root-dir } @Override @@ -832,7 +929,7 @@ public class SchematicCommands { //FAWE start boolean checkFilesize = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS - && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1; + && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1; double directorysizeKb = 0; String curFilepath = file.getAbsolutePath(); @@ -862,7 +959,7 @@ public class SchematicCommands { } - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) { if (numFiles == -1) { numFiles = 0; @@ -875,7 +972,7 @@ public class SchematicCommands { } } } - int limit = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT; + int limit = actor.getLimit().SCHEM_FILE_NUM_LIMIT; if (numFiles >= limit) { TextComponent noSlotsErr = TextComponent.of( //TODO - to be moved into captions/translatablecomponents @@ -894,10 +991,7 @@ public class SchematicCommands { if (transform.isIdentity()) { target = clipboard; } else { - FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform); - target = new BlockArrayClipboard(result.getTransformedRegion()); - target.setOrigin(clipboard.getOrigin()); - Operations.completeLegacy(result.copyTo(target)); + target = clipboard.transform(transform); } try (Closer closer = Closer.create()) { @@ -926,7 +1020,7 @@ public class SchematicCommands { if (checkFilesize) { double curKb = filesizeKb + directorysizeKb; - int allocatedKb = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT; + int allocatedKb = actor.getLimit().SCHEM_FILE_SIZE_LIMIT; if (overwrite) { curKb -= oldKbOverwritten; @@ -961,11 +1055,11 @@ public class SchematicCommands { actor.print(kbRemainingNotif); } - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) { TextComponent slotsRemainingNotif = TextComponent.of( //TODO - to be moved into captions/translatablecomponents - "You have " + (Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT - numFiles) + "You have " + (actor.getLimit().SCHEM_FILE_NUM_LIMIT - numFiles) + " schematic file slots left.", TextColor.GRAY ); @@ -979,7 +1073,34 @@ public class SchematicCommands { //FAWE end return null; } + } + private static class SchematicShareTask extends SchematicOutputTask> { + private final Actor actor; + private final String name; + private final ClipboardShareDestination destination; + + SchematicShareTask(Actor actor, + ClipboardHolder holder, + ClipboardShareDestination destination, + ClipboardFormat format, + String name) { + super(actor, format, holder); + this.actor = actor; + this.name = name; + this.destination = destination; + } + + @Override + public Consumer call() throws Exception { + ClipboardShareMetadata metadata = new ClipboardShareMetadata( + format, + this.actor.getName(), + name == null ? actor.getName() + "-" + System.currentTimeMillis() : name + ); + + return destination.share(metadata, this::writeToOutputStream); + } } private static class SchematicListTask implements Callable { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 64e3c8a81..ddca046ff 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.command.argument.SelectorChoice; import com.sk89q.worldedit.command.tool.NavigationWand; @@ -38,6 +39,8 @@ import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Locatable; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; @@ -76,8 +79,6 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.storage.ChunkStore; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; @@ -262,12 +263,12 @@ public class SelectionCommands { actor.print(Caption.of( "worldedit.chunk.selected-multiple", - TextComponent.of(minChunk.getBlockX()), - TextComponent.of(minChunk.getBlockY()), - TextComponent.of(minChunk.getBlockZ()), - TextComponent.of(maxChunk.getBlockX()), - TextComponent.of(maxChunk.getBlockY()), - TextComponent.of(maxChunk.getBlockZ()) + TextComponent.of(minChunk.x()), + TextComponent.of(minChunk.y()), + TextComponent.of(minChunk.z()), + TextComponent.of(maxChunk.x()), + TextComponent.of(maxChunk.y()), + TextComponent.of(maxChunk.z()) )); } else { BlockVector3 minChunk; @@ -290,9 +291,9 @@ public class SelectionCommands { actor.print(Caption.of( "worldedit.chunk.selected", - TextComponent.of(minChunk.getBlockX()), - TextComponent.of(minChunk.getBlockY()), - TextComponent.of(minChunk.getBlockZ()) + TextComponent.of(minChunk.x()), + TextComponent.of(minChunk.y()), + TextComponent.of(minChunk.z()) )); } @@ -325,22 +326,28 @@ public class SelectionCommands { //FAWE start session.loadDefaults(player, true); //FAWE end - String wandId = navWand ? session.getNavWandItem() : session.getWandItem(); - if (wandId == null) { - wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem; + BaseItem wand = navWand ? session.getNavWandBaseItem() : session.getWandBaseItem(); + if (wand == null) { + String wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem; + //FAWE start - allow item NBT + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setSession(session); + try { + wand = WorldEdit.getInstance().getItemFactory().parseFromInput(wandId, parserContext); + } catch (InputParseException e) { + player.print(Caption.of("worldedit.wand.invalid")); + return; + } } - ItemType itemType = ItemTypes.parse(wandId); - if (itemType == null) { - player.print(Caption.of("worldedit.wand.invalid")); - return; - } - player.giveItem(new BaseItemStack(itemType, 1)); + player.giveItem(new BaseItemStack(wand.getType(), wand.getNbtReference(), 1)); + //FAWE end //FAWE start - instance-iate session if (navWand) { - session.setTool(itemType, NavigationWand.INSTANCE); + session.setTool(wand, NavigationWand.INSTANCE); player.print(Caption.of("worldedit.wand.navwand.info")); } else { - session.setTool(itemType, SelectionWand.INSTANCE); + session.setTool(wand, SelectionWand.INSTANCE); player.print(Caption.of("worldedit.wand.selwand.info")); //FAWE end } @@ -538,10 +545,10 @@ public class SelectionCommands { .subtract(region.getMinimumPoint()).add(1, 1, 1); BlockVector3 origin = clipboard.getOrigin(); - String sizeStr = size.getBlockX() + "*" + size.getBlockY() + "*" + size.getBlockZ(); - String originStr = origin.getBlockX() + "," + origin.getBlockY() + "," + origin.getBlockZ(); + String sizeStr = size.x() + "*" + size.y() + "*" + size.z(); + String originStr = origin.x() + "," + origin.y() + "," + origin.z(); - long numBlocks = ((long) size.getBlockX() * size.getBlockY() * size.getBlockZ()); + long numBlocks = ((long) size.x() * size.y() * size.z()); actor.print(Caption.of( "worldedit.size.offset", TextComponent.of(name), @@ -755,13 +762,7 @@ public class SelectionCommands { } if (setDefaultSelector) { - RegionSelectorType found = null; - for (RegionSelectorType type : RegionSelectorType.values()) { - if (type.getSelectorClass() == newSelector.getClass()) { - found = type; - break; - } - } + RegionSelectorType found = RegionSelectorType.getForSelector(newSelector); if (found != null) { session.setDefaultRegionSelector(found); @@ -838,7 +839,7 @@ public class SelectionCommands { toolTip = TextComponent.of(state.getAsString()); blockName = blockName.append(TextComponent.of("*")); } else { - toolTip = TextComponent.of(blockType.getId()); + toolTip = TextComponent.of(blockType.id()); } blockName = blockName.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, toolTip)); line.append(blockName); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index b98785631..074711521 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -66,6 +67,7 @@ public class SnapshotUtilCommands { ) @Logging(REGION) @CommandPermissions("worldedit.snapshots.restore") + @SynchronousSettingExpected public void restore( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(name = "snapshot", desc = "The snapshot to restore", def = "") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java index cb24daec5..fdd86498f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java @@ -66,10 +66,11 @@ public class SuperPickaxeCommands { int range ) throws WorldEditException { - LocalConfiguration config = we.getConfiguration(); - - if (range > config.maxSuperPickaxeSize) { - player.print(Caption.of("worldedit.tool.superpickaxe.max-range", TextComponent.of(config.maxSuperPickaxeSize))); + if (range > player.getLimit().MAX_SUPER_PICKAXE_SIZE) { + player.print(Caption.of( + "worldedit.tool.superpickaxe.max-range", + TextComponent.of(player.getLimit().MAX_SUPER_PICKAXE_SIZE) + )); return; } session.setSuperPickaxe(new AreaPickaxe(range)); @@ -89,10 +90,11 @@ public class SuperPickaxeCommands { double range ) throws WorldEditException { - LocalConfiguration config = we.getConfiguration(); - - if (range > config.maxSuperPickaxeSize) { - player.print(Caption.of("worldedit.tool.superpickaxe.max-range", TextComponent.of(config.maxSuperPickaxeSize))); + if (range > player.getLimit().MAX_SUPER_PICKAXE_SIZE) { + player.print(Caption.of( + "worldedit.tool.superpickaxe.max-range", + TextComponent.of(player.getLimit().MAX_SUPER_PICKAXE_SIZE) + )); return; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 8395b2e2d..f3be41469 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -149,7 +149,7 @@ public class ToolCommands { throws InvalidToolBindException { //FAWE start isBrush = session.getTool(player) instanceof BrushTool; - session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); + session.setTool(player.getItemInHand(HandSide.MAIN_HAND), null); //FAWE end player.print(Caption.of(isBrush ? "worldedit.brush.none.equip" : "worldedit.tool.none.equip")); } @@ -163,7 +163,7 @@ public class ToolCommands { String translationKey ) throws InvalidToolBindException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), tool); + session.setTool(itemStack, tool); player.print(Caption.of(translationKey, itemStack.getRichName())); sendUnbindInstruction(player, UNBIND_COMMAND_COMPONENT); } @@ -297,10 +297,11 @@ public class ToolCommands { int range ) throws WorldEditException { - LocalConfiguration config = we.getConfiguration(); - - if (range > config.maxSuperPickaxeSize) { - player.print(Caption.of("worldedit.tool.superpickaxe.max-range", TextComponent.of(config.maxSuperPickaxeSize))); + if (range > player.getLimit().MAX_SUPER_PICKAXE_SIZE) { + player.print(Caption.of( + "worldedit.tool.superpickaxe.max-range", + TextComponent.of(player.getLimit().MAX_SUPER_PICKAXE_SIZE) + )); return; } setTool(player, session, new FloodFillTool(range, pattern), "worldedit.tool.floodfill.equip"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index 0694b2af3..48fb76318 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -154,7 +154,7 @@ public class ToolUtilCommands { @Arg(desc = "The size of the brush") int size ) throws WorldEditException { - we.checkMaxBrushRadius(size); + we.checkMaxBrushRadius(size, player); session.getBrushTool(player).setSize(size); player.print(Caption.of("worldedit.tool.size.set")); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index aca13bc46..c7c6ab9a1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -44,25 +44,19 @@ import com.sk89q.worldedit.command.util.EntityRemover; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.PrintCommandHelp; import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.function.EntityFunction; -import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.mask.BlockTypeMask; -import com.sk89q.worldedit.function.mask.BoundedHeightMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.mask.MaskIntersection; -import com.sk89q.worldedit.function.mask.Masks; -import com.sk89q.worldedit.function.mask.RegionMask; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.visitor.DownwardVisitor; import com.sk89q.worldedit.function.visitor.EntityVisitor; -import com.sk89q.worldedit.function.visitor.RecursiveVisitor; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.VertHeight; import com.sk89q.worldedit.internal.expression.EvaluationException; @@ -70,10 +64,8 @@ import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector2; -import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; -import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.Component; @@ -229,6 +221,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fill( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") @@ -246,10 +239,12 @@ public class UtilityCommands { double radius = radiusExp.evaluate(); //FAWE end radius = Math.max(1, radius); - we.checkMaxRadius(radius); + we.checkMaxRadius(radius, actor); depth = Math.max(1, depth); + we.checkMaxRadius(depth, actor); BlockVector3 pos = session.getPlacementPosition(actor); + we.checkExtentHeightBounds(pos, editSession); int affected = editSession.fillDirection(pos, pattern, radius, depth, direction); actor.print(Caption.of("worldedit.fill.created", TextComponent.of(affected))); return affected; @@ -318,6 +313,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill.recursive") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fillr( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") @@ -333,11 +329,12 @@ public class UtilityCommands { double radius = radiusExp.evaluate(); //FAWE end radius = Math.max(1, radius); - we.checkMaxRadius(radius); + we.checkMaxRadius(radius, actor); depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth); - we.checkMaxRadius(radius); + we.checkMaxRadius(radius, actor); BlockVector3 pos = session.getPlacementPosition(actor); + we.checkExtentHeightBounds(pos, editSession); int affected = editSession.fillXZ(pos, pattern, radius, depth, true); actor.print(Caption.of("worldedit.fillr.created", TextComponent.of(affected))); return affected; @@ -349,6 +346,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.drain") @Logging(PLACEMENT) + @SynchronousSettingExpected public int drain( Actor actor, LocalSession session, EditSession editSession, //FAWE start - we take an expression over a double @@ -364,8 +362,10 @@ public class UtilityCommands { //FAWE end double radius = radiusExp.evaluate(); radius = Math.max(0, radius); - we.checkMaxRadius(radius); - int affected = editSession.drainArea(session.getPlacementPosition(actor), radius, waterlogged, plants); + we.checkMaxRadius(radius, actor); + BlockVector3 pos = session.getPlacementPosition(actor); + we.checkExtentHeightBounds(pos, editSession); + int affected = editSession.drainArea(pos, radius, waterlogged, plants); actor.print(Caption.of("worldedit.drain.drained", TextComponent.of(affected))); return affected; } @@ -377,14 +377,17 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixlava") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fixLava( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") double radius ) throws WorldEditException { radius = Math.max(0, radius); - we.checkMaxRadius(radius); - int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.LAVA); + we.checkMaxRadius(radius, actor); + BlockVector3 pos = session.getPlacementPosition(actor); + we.checkExtentHeightBounds(pos, editSession); + int affected = editSession.fixLiquid(pos, radius, BlockTypes.LAVA); actor.print(Caption.of("worldedit.fixlava.fixed", TextComponent.of(affected))); return affected; } @@ -396,14 +399,17 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixwater") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fixWater( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") double radius ) throws WorldEditException { radius = Math.max(0, radius); - we.checkMaxRadius(radius); - int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.WATER); + we.checkMaxRadius(radius, actor); + BlockVector3 pos = session.getPlacementPosition(actor); + we.checkExtentHeightBounds(pos, editSession); + int affected = editSession.fixLiquid(pos, radius, BlockTypes.WATER); actor.print(Caption.of("worldedit.fixwater.fixed", TextComponent.of(affected))); return affected; } @@ -415,6 +421,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeAbove( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") @@ -423,7 +430,7 @@ public class UtilityCommands { Integer height ) throws WorldEditException { size = Math.max(1, size); - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); height = height != null ? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1) @@ -440,6 +447,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removebelow") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeBelow( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") @@ -448,7 +456,7 @@ public class UtilityCommands { Integer height ) throws WorldEditException { size = Math.max(1, size); - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); height = height != null ? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1) @@ -465,6 +473,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removenear") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeNear( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The mask of blocks to remove") @@ -476,7 +485,7 @@ public class UtilityCommands { new MaskTraverser(mask).setNewExtent(editSession); //FAWE end radius = Math.max(1, radius); - we.checkMaxRadius(radius); + we.checkMaxRadius(radius, actor); int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, radius); actor.print(Caption.of("worldedit.removenear.removed", TextComponent.of(affected))); @@ -503,7 +512,7 @@ public class UtilityCommands { new MaskTraverser(from).setNewExtent(editSession); //FAWE end radius = Math.max(1, radius); - we.checkMaxRadius(radius); + we.checkMaxRadius(radius, actor); BlockVector3 base = session.getPlacementPosition(actor); BlockVector3 min = base.subtract(radius, radius, radius); @@ -527,6 +536,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.snow") @Logging(PLACEMENT) + @SynchronousSettingExpected public int snow( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to snow in", def = "10") @@ -542,15 +552,15 @@ public class UtilityCommands { ) throws WorldEditException { size = Math.max(1, size); height = Math.max(1, height); - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); BlockVector3 position = session.getPlacementPosition(actor); CylinderRegion region = new CylinderRegion( position, Vector2.at(size, size), - position.getBlockY() - height, - position.getBlockY() + height + position.y() - height, + position.y() + height ); int affected = editSession.simulateSnow(region, stack); actor.print(Caption.of( @@ -566,6 +576,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.thaw") @Logging(PLACEMENT) + @SynchronousSettingExpected public int thaw( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to thaw in", def = "10") @@ -579,7 +590,7 @@ public class UtilityCommands { ) throws WorldEditException { size = Math.max(1, size); height = Math.max(1, height); - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); int affected = editSession.thaw(session.getPlacementPosition(actor), size, height); actor.print(Caption.of( @@ -595,6 +606,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.green") @Logging(PLACEMENT) + @SynchronousSettingExpected public int green( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to convert in", def = "10") @@ -610,7 +622,7 @@ public class UtilityCommands { ) throws WorldEditException { size = Math.max(1, size); height = Math.max(1, height); - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); final boolean onlyNormalDirt = !convertCoarse; final int affected = editSession.green( @@ -629,17 +641,16 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.extinguish") @Logging(PLACEMENT) + @SynchronousSettingExpected public int extinguish( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the square to remove in", def = "") Integer radius ) throws WorldEditException { - LocalConfiguration config = we.getConfiguration(); - - int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40; + int defaultRadius = actor.getLimit().MAX_RADIUS != -1 ? Math.min(40, actor.getLimit().MAX_RADIUS) : 40; int size = radius != null ? Math.max(1, radius) : defaultRadius; - we.checkMaxRadius(size); + we.checkMaxRadius(size, actor); Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE); int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, size); @@ -685,12 +696,12 @@ public class UtilityCommands { actor.print(Caption.of("worldedit.butcher.explain-all")); return 0; } else if (radius == -1) { - if (config.butcherMaxRadius != -1) { - radius = config.butcherMaxRadius; + if (actor.getLimit().MAX_BUTCHER_RADIUS != -1) { + radius = actor.getLimit().MAX_BUTCHER_RADIUS; } } - if (config.butcherMaxRadius != -1) { - radius = Math.min(radius, config.butcherMaxRadius); + if (actor.getLimit().MAX_BUTCHER_RADIUS != -1) { + radius = Math.min(radius, actor.getLimit().MAX_BUTCHER_RADIUS); } CreatureButcher flags = new CreatureButcher(actor); @@ -845,55 +856,6 @@ public class UtilityCommands { } } -// @Command( -// name = "/hollowr", -// desc = "Hollow out a space recursively with a pattern" -// ) -// @CommandPermissions("worldedit.hollowr") -// @Logging(PLACEMENT) -// public int hollowr( -// Actor actor, -// LocalSession session, -// EditSession editSession, -// @Arg(desc = "The radius to hollow out") Expression radiusExp, -// @ArgFlag(name = 'p', desc = "The blocks to fill with") Pattern pattern, -// @ArgFlag(name = 'm', desc = "The blocks remove", def = "") Mask mask -// ) throws WorldEditException { -// //FAWE start -// double radius = radiusExp.evaluate(); -// //FAWE end -// radius = Math.max(1, radius); -// we.checkMaxRadius(radius); -// if (mask == null) { -// Mask mask = new MaskIntersection( -// new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))), -// new BoundedHeightMask( -// Math.max(lowerBound, minY), -// Math.min(maxY, origin.getBlockY()) -// ), -// Masks.negate(new ExistingBlockMask(this)) -// ); -// } -// -// // Want to replace blocks -// BlockReplace replace = new BlockReplace(this, pattern); -// -// // Pick how we're going to visit blocks -// RecursiveVisitor visitor; -// //FAWE start - provide extent for preloading, min/max y -// if (recursive) { -// visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), minY, maxY, this); -// } else { -// visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), minY, maxY, this); -// } -// //FAWE end -// -// BlockVector3 pos = session.getPlacementPosition(actor); -// int affected = editSession.res(pos, pattern, radius, depth, true); -// actor.print(Caption.of("worldedit.fillr.created", TextComponent.of(affected))); -// return affected; -// } - public static List> filesToEntry(final File root, final List files, final UUID uuid) { return files.stream() .map(input -> { // Keep this functional, as transform is evaluated lazily diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index db611b75c..04274a79a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -22,6 +22,8 @@ package com.sk89q.worldedit.command; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweVersion; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.util.UpdateNotification; import com.intellectualsites.paster.IncendoPaster; import com.sk89q.worldedit.LocalSession; @@ -97,6 +99,8 @@ public class WorldEditCommands { .getConfiguration())); //FAWE start Fawe.instance().setupConfigs(); + FaweLimit.MAX.CONFIRM_LARGE = + Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS; //FAWE end actor.print(Caption.of("worldedit.reload.config")); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardFormatConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardFormatConverter.java new file mode 100644 index 000000000..cfa0a1ed4 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardFormatConverter.java @@ -0,0 +1,76 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestination; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; +import java.util.Set; + +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; + +public class ClipboardFormatConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(ClipboardFormat.class), + new ClipboardFormatConverter() + ); + } + + private final TextComponent choices; + + private ClipboardFormatConverter() { + this.choices = TextComponent.of("any clipboard format"); + } + + @Override + public Component describeAcceptableArguments() { + return this.choices; + } + + @Override + public List getSuggestions(String input, InjectedValueAccess context) { + ClipboardShareDestination destination = context.injectedValue(Key.of(ClipboardShareDestination.class)).orElse(null); + + return limitByPrefix(ClipboardFormats.getAll().stream() + .filter(format -> destination == null || destination.supportsFormat(format)) + .map(ClipboardFormat::getAliases) + .flatMap(Set::stream), input); + } + + @Override + public ConversionResult convert(String s, InjectedValueAccess injectedValueAccess) { + ClipboardFormat result = ClipboardFormats.findByAlias(s); + return result == null + ? FailedConversion.from(new IllegalArgumentException("Not a valid schematic format: " + s)) + : SuccessfulConversion.fromSingle(result); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardShareDestinationConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardShareDestinationConverter.java new file mode 100644 index 000000000..5af81bb1d --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ClipboardShareDestinationConverter.java @@ -0,0 +1,72 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestination; +import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestinations; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; +import java.util.Set; + +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; + +public class ClipboardShareDestinationConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(ClipboardShareDestination.class), + new ClipboardShareDestinationConverter() + ); + } + + private final TextComponent choices; + + private ClipboardShareDestinationConverter() { + this.choices = TextComponent.of("any clipboard share destination"); + } + + @Override + public Component describeAcceptableArguments() { + return this.choices; + } + + @Override + public List getSuggestions(String input, InjectedValueAccess context) { + return limitByPrefix(ClipboardShareDestinations.getAll().stream() + .map(ClipboardShareDestination::getAliases) + .flatMap(Set::stream), input); + } + + @Override + public ConversionResult convert(String s, InjectedValueAccess injectedValueAccess) { + ClipboardShareDestination result = ClipboardShareDestinations.findByAlias(s); + return result == null + ? FailedConversion.from(new IllegalArgumentException("Not a valid clipboard share destination: " + s)) + : SuccessfulConversion.fromSingle(result); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java index 1a382d43c..d3189f1f1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java @@ -113,8 +113,7 @@ public class FactoryConverter implements ArgumentConverter { ); } - @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { + private ParserContext createContext(InjectedValueAccess context) { Actor actor = context.injectedValue(Key.of(Actor.class)) .orElseThrow(() -> new IllegalStateException("No actor")); LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); @@ -134,11 +133,19 @@ public class FactoryConverter implements ArgumentConverter { parserContext.setSession(session); parserContext.setRestricted(true); parserContext.setInjected(context); + parserContext.setTryLegacy(actor.getLimit().ALLOW_LEGACY); if (contextTweaker != null) { contextTweaker.accept(parserContext); } + return parserContext; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + ParserContext parserContext = createContext(context); + try { return SuccessfulConversion.fromSingle( factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext) @@ -150,7 +157,9 @@ public class FactoryConverter implements ArgumentConverter { @Override public List getSuggestions(String input, InjectedValueAccess context) { - return factoryExtractor.apply(worldEdit).getSuggestions(input); + ParserContext parserContext = createContext(context); + + return factoryExtractor.apply(worldEdit).getSuggestions(input, parserContext); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/OffsetConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/OffsetConverter.java index 88b74a05f..22c755cb5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/OffsetConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/OffsetConverter.java @@ -98,9 +98,9 @@ public class OffsetConverter implements ArgumentConverter { // Create an affine transform of the columns (col4 is empty due to no translation) AffineTransform transform = new AffineTransform( - m1.getX(), m2.getX(), m3.getX(), 0, - m1.getY(), m2.getY(), m3.getY(), 0, - m1.getZ(), m2.getZ(), m3.getZ(), 0 + m1.x(), m2.x(), m3.x(), 0, + m1.y(), m2.y(), m3.y(), 0, + m1.z(), m2.z(), m3.z(), 0 ); return transform diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/WorldConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/WorldConverter.java index fd043d440..54492497a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/WorldConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/WorldConverter.java @@ -65,7 +65,7 @@ public class WorldConverter implements ArgumentConverter { @Override public List getSuggestions(String input, InjectedValueAccess context) { return getWorlds() - .map(World::getId) + .map(World::id) .filter(world -> world.startsWith(input)) .collect(Collectors.toList()); } @@ -73,7 +73,7 @@ public class WorldConverter implements ArgumentConverter { @Override public ConversionResult convert(String s, InjectedValueAccess injectedValueAccess) { World result = getWorlds() - .filter(world -> world.getId().equals(s)) + .filter(world -> world.id().equals(s)) .findAny().orElse(null); return result == null ? FailedConversion.from(new IllegalArgumentException( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java index 270468aa1..d1bd7bbd3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java @@ -20,8 +20,8 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.command.argument.ExpressionConverter - * @see com.sk89q.worldedit.command.argument.LocationConverter + * {@link com.sk89q.worldedit.command.argument.ExpressionConverter}, + * {@link com.sk89q.worldedit.command.argument.LocationConverter} */ @org.enginehub.piston.util.NonnullByDefault package com.sk89q.worldedit.command.argument; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/package-info.java index 61d4ea41d..4ffda131d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/package-info.java @@ -1,6 +1,6 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.command.HistorySubCommands + * {@link com.sk89q.worldedit.command.HistorySubCommands} */ package com.sk89q.worldedit.command; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index b9a2ee888..6a9a6fd95 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -66,7 +66,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { if (!config.allowedDataCycleBlocks.isEmpty() && !player.hasPermission("worldedit.override.data-cycler") - && !config.allowedDataCycleBlocks.contains(block.getBlockType().getId())) { + && !config.allowedDataCycleBlocks.contains(block.getBlockType().id())) { player.print(Caption.of("worldedit.tool.data-cycler.block-not-permitted")); return true; } @@ -89,7 +89,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { Property objProp = (Property) currentProperty; BaseBlock newBlock = block.with(objProp, currentProperty.getValues().get(index)); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { editSession.setBlock(blockPoint, newBlock); player.print(Caption.of( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 75ef200c6..b37505d8b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -63,7 +63,7 @@ public class BlockReplacer implements DoubleActionBlockTool { ) { BlockBag bag = session.getBlockBag(player); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { BlockVector3 position = clicked.toVector().toBlockPoint(); editSession.setBlock(position, pattern); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index d6c44fa66..6021102a2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -380,7 +380,7 @@ public class BrushTool pitch = 23 - (pitch / 4); d += (int) (Math.sin(Math.toRadians(pitch)) * 50); final Vector3 vector = loc.getDirection().withY(0).normalize().multiply(d) - .add(loc.getX(), loc.getY(), loc.getZ()); + .add(loc.x(), loc.y(), loc.z()); return offset(vector, loc).toBlockPoint(); } case TARGET_POINT_HEIGHT: { @@ -477,7 +477,7 @@ public class BrushTool try { new PatternTraverser(current).reset(editSession); double size = current.getSize(); - WorldEdit.getInstance().checkMaxBrushRadius(size); + WorldEdit.getInstance().checkMaxBrushRadius(size, player); brush.build(editSession, target.toBlockPoint(), current.getMaterial(), size); } catch (MaxChangedBlocksException e) { player.print(Caption.of("worldedit.tool.max-block-changes")); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index b35865fb3..5cec2ec11 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -62,7 +62,7 @@ public class SinglePickaxe implements BlockTool { return false; } - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); editSession.setBlock(blockPoint, BlockTypes.AIR.getDefaultState()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java index 614bbcf32..415cade93 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java @@ -59,7 +59,7 @@ public class StackTool implements BlockTool { } BlockBag bag = session.getBlockBag(player); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { BlockStateHolder block = editSession.getFullBlock(clicked.toVector().toBlockPoint()); try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java index 1f52ff103..db92f6af9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java @@ -60,7 +60,7 @@ public class TreePlanter implements BlockTool { @Nullable Direction face ) { - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { boolean successful = false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java index 8efe2ab77..938a2f8dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java @@ -40,4 +40,15 @@ public interface Brush { */ void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException; + //FAWE start + /** + * If this brush is expected to set blocks synchronously, i.e. from one thread (at a time) + * + * @since 2.12.0 + */ + default boolean setsSynchronously() { + return true; + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java index b82601288..bfa19b7e3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java @@ -38,11 +38,11 @@ public class GravityBrush implements Brush { public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { //FAWE start - Ours operates differently to upstream, but does the same - double endY = position.getY() + size; - double startPerformY = Math.max(editSession.getMinY(), position.getY() - size); + double endY = position.y() + size; + double startPerformY = Math.max(editSession.getMinY(), position.y() - size); double startCheckY = fullHeight ? editSession.getMinY() : startPerformY; - for (double x = position.getX() + size; x > position.getX() - size; --x) { - for (double z = position.getZ() + size; z > position.getZ() - size; --z) { + for (double x = position.x() + size; x > position.x() - size; --x) { + for (double z = position.z() + size; z > position.z() - size; --z) { double freeSpot = startCheckY; for (double y = startCheckY; y <= endY; y++) { BlockState block = editSession.getBlock((int) x, (int) y, (int) z); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java index a2854a8c7..b8980afc8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java @@ -3,7 +3,6 @@ package com.sk89q.worldedit.command.util.annotation; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.util.task.InterruptableCondition; import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.event.Event; import com.sk89q.worldedit.event.platform.CommandEvent; @@ -57,7 +56,7 @@ public @interface Confirm { .orElseThrow(IncompleteRegionException::new); BlockVector3 pos1 = region.getMinimumPoint(); BlockVector3 pos2 = region.getMaximumPoint(); - long area = (pos2.getX() - pos1.getX()) * (pos2.getZ() - pos1.getZ() + 1) + long area = (pos2.x() - pos1.x()) * (pos2.z() - pos1.z() + 1) * (long) value; long max = 2 << 18; if (max != -1 && area > max) { @@ -75,7 +74,7 @@ public @interface Confirm { if (checkExisting(context)) { return true; } - int max = WorldEdit.getInstance().getConfiguration().maxRadius; + int max = actor.getLimit().MAX_RADIUS; if (max != -1 && value > max) { actor.print(Caption.of("fawe.cancel.reason.confirm.radius", value, max, getArgs(context) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java index 067f9cfeb..5d6b66483 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java @@ -12,7 +12,7 @@ import java.lang.reflect.Method; import java.util.Optional; /** - * Logs called commands to a logger. + * Handles commands indicated as requiring confirmation. */ public class ConfirmHandler implements CommandCallListener { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java index 9e1dc106f..037c94e5b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java @@ -11,7 +11,7 @@ import java.lang.reflect.Method; import java.util.Optional; /** - * Logs called commands to a logger. + * Initialises preloading of chunks. */ public class PreloadHandler implements CommandCallListener { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java new file mode 100644 index 000000000..6d94fb3ff --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java @@ -0,0 +1,22 @@ +package com.sk89q.worldedit.command.util.annotation; + +import org.enginehub.piston.inject.InjectAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates it is expected that blocks will only be set synchronously, i.e. from one thread (at a time) + * + * @since 2.12.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ + ElementType.METHOD +}) +@InjectAnnotation +public @interface SynchronousSettingExpected { + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java index dc15d98d6..f7f293277 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java @@ -1,14 +1,15 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.command.util.annotation.AllowedRegion - * @see com.sk89q.worldedit.command.util.annotation.Confirm - * @see com.sk89q.worldedit.command.util.annotation.ConfirmHandler - * @see com.sk89q.worldedit.command.util.annotation.Link - * @see com.sk89q.worldedit.command.util.annotation.PatternList - * @see com.sk89q.worldedit.command.util.annotation.Preload - * @see com.sk89q.worldedit.command.util.annotation.PreloadHandler - * @see com.sk89q.worldedit.command.util.annotation.Step - * @see com.sk89q.worldedit.command.util.annotation.Time + * {@link com.sk89q.worldedit.command.util.annotation.AllowedRegion}, + * {@link com.sk89q.worldedit.command.util.annotation.Confirm}, + * {@link com.sk89q.worldedit.command.util.annotation.ConfirmHandler}, + * {@link com.sk89q.worldedit.command.util.annotation.Link}, + * {@link com.sk89q.worldedit.command.util.annotation.PatternList}, + * {@link com.sk89q.worldedit.command.util.annotation.Preload}, + * {@link com.sk89q.worldedit.command.util.annotation.PreloadHandler}, + * {@link com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected}, + * {@link com.sk89q.worldedit.command.util.annotation.Step}, + * {@link com.sk89q.worldedit.command.util.annotation.Time} */ package com.sk89q.worldedit.command.util.annotation; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java index ceb07a71e..b369ddd87 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java @@ -21,10 +21,10 @@ package com.sk89q.worldedit.entity; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.entity.EntityTypes; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; @@ -47,7 +47,7 @@ public class BaseEntity implements NbtValued { private final EntityType type; @Nullable - private LazyReference nbtData; + private LazyReference nbtData; /** * Create a new base entity. @@ -56,6 +56,7 @@ public class BaseEntity implements NbtValued { * @param nbtData NBT data * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)} */ + @SuppressWarnings("this-escape") @Deprecated public BaseEntity(EntityType type, CompoundTag nbtData) { this(type); @@ -68,7 +69,7 @@ public class BaseEntity implements NbtValued { * @param type the entity type * @param nbtData NBT data */ - public BaseEntity(EntityType type, LazyReference nbtData) { + public BaseEntity(EntityType type, LazyReference nbtData) { this(type); setNbtReference(nbtData); } @@ -87,6 +88,7 @@ public class BaseEntity implements NbtValued { * * @param other the object to clone */ + @SuppressWarnings("this-escape") public BaseEntity(BaseEntity other) { checkNotNull(other); this.type = other.getType(); @@ -95,12 +97,12 @@ public class BaseEntity implements NbtValued { @Nullable @Override - public LazyReference getNbtReference() { + public LazyReference getNbtReference() { return nbtData; } @Override - public void setNbtReference(@Nullable LazyReference nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { this.nbtData = nbtData; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java index 277d755b1..11561f313 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java @@ -22,19 +22,15 @@ package com.sk89q.worldedit.entity; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard; import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismatchException; import com.fastasyncworldedit.core.regions.FaweMaskManager; import com.fastasyncworldedit.core.util.MainUtil; -import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; -import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.util.DeprecationUtil; @@ -43,7 +39,6 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; -import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; @@ -428,11 +423,12 @@ public interface Player extends Entity, Actor { if (Settings.settings().CLIPBOARD.USE_DISK && Settings.settings().CLIPBOARD.DELETE_ON_LOGOUT) { session.deleteClipboardOnDisk(); } else if (Settings.settings().CLIPBOARD.USE_DISK) { - Fawe.instance().getClipboardExecutor().submit(getUniqueId(), () -> session.setClipboard(null)); + Fawe.instance().submitUUIDKeyQueuedTask(getUniqueId(), () -> session.setClipboard(null)); } else if (Settings.settings().CLIPBOARD.DELETE_ON_LOGOUT) { session.setClipboard(null); } - if (Settings.settings().HISTORY.DELETE_ON_LOGOUT) { + if (!Settings.settings().HISTORY.USE_DISK && Settings.settings().HISTORY.DELETE_ON_LOGOUT + || Settings.settings().HISTORY.USE_DISK && Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT) { session.clearHistory(); } } @@ -440,32 +436,8 @@ public interface Player extends Entity, Actor { void sendTitle(Component title, Component sub); /** - * Loads any history items from disk: - Should already be called if history on disk is enabled. + * Loads clipboard file from disk if it exists */ - default void loadClipboardFromDisk() { - File file = MainUtil.getFile( - Fawe.platform().getDirectory(), - Settings.settings().PATHS.CLIPBOARD + File.separator + getUniqueId() + ".bd" - ); - try { - getSession().loadClipboardFromDisk(file); - } catch (FaweClipboardVersionMismatchException e) { - print(e.getComponent()); - } catch (RuntimeException e) { - print(Caption.of("fawe.error.clipboard.invalid")); - e.printStackTrace(); - print(Caption.of("fawe.error.stacktrace")); - print(Caption.of("fawe.error.clipboard.load.failure")); - print(Caption.of("fawe.error.clipboard.invalid.info", file.getName(), file.length())); - print(Caption.of("fawe.error.stacktrace")); - } catch (Exception e) { - print(Caption.of("fawe.error.clipboard.invalid")); - e.printStackTrace(); - print(Caption.of("fawe.error.stacktrace")); - print(Caption.of("fawe.error.no-failure")); - print(Caption.of("fawe.error.clipboard.invalid.info", file.getName(), file.length())); - print(Caption.of("fawe.error.stacktrace")); - } - } + void loadClipboardFromDisk(); //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java index 14ecb48f1..f436ce576 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java @@ -23,11 +23,16 @@ import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser; import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.internal.registry.AbstractFactory; +import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BaseBlock; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -67,4 +72,21 @@ public class BlockFactory extends AbstractFactory { return blocks; } + //FAWE start + @Override + public BaseBlock parseFromInput(String input, ParserContext context) throws InputParseException { + BaseBlock match; + + for (InputParser parser : parsers) { + match = parser.parseFromInput(input, context); + + if (match != null) { + return match; + } + } + + throw new NoMatchException(TranslatableComponent.of("worldedit.error.no-match", TextComponent.of(input))); + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java index b1858a12d..8c907f42a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java @@ -22,7 +22,13 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.extension.factory.parser.DefaultItemParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.NoMatchException; +import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.internal.registry.AbstractFactory; +import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; public class ItemFactory extends AbstractFactory { @@ -35,4 +41,21 @@ public class ItemFactory extends AbstractFactory { super(worldEdit, new DefaultItemParser(worldEdit)); } + //FAWE start + @Override + public BaseItem parseFromInput(String input, ParserContext context) throws InputParseException { + BaseItem match; + + for (InputParser parser : parsers) { + match = parser.parseFromInput(input, context); + + if (match != null) { + return match; + } + } + + throw new NoMatchException(TranslatableComponent.of("worldedit.error.no-match", TextComponent.of(input))); + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index 24c674f0b..dce3e1c4f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -25,6 +25,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.mask.AngleMaskParser import com.fastasyncworldedit.core.extension.factory.parser.mask.BesideMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser; +import com.fastasyncworldedit.core.extension.factory.parser.mask.HotbarMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ROCAngleMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.RadiusMaskParser; @@ -58,10 +59,8 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.internal.registry.AbstractFactory; -import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.util.formatting.text.TextComponent; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -74,21 +73,13 @@ import java.util.stream.Collectors; */ public final class MaskFactory extends AbstractFactory { - //FAWE start - rich mask parsing - private final RichMaskParser richMaskParser; - //FAWE end - /** * Create a new mask registry. * * @param worldEdit the WorldEdit instance */ public MaskFactory(WorldEdit worldEdit) { - super(worldEdit, new BlocksMaskParser(worldEdit)); - - //FAWE start - rich mask parsing - richMaskParser = new RichMaskParser(worldEdit); - //FAWE end + super(worldEdit, new BlocksMaskParser(worldEdit), new RichMaskParser(worldEdit)); register(new ExistingMaskParser(worldEdit)); register(new AirMaskParser(worldEdit)); @@ -110,6 +101,7 @@ public final class MaskFactory extends AbstractFactory { register(new BesideMaskParser(worldEdit)); register(new ExtremaMaskParser(worldEdit)); register(new FalseMaskParser(worldEdit)); + register(new HotbarMaskParser(worldEdit)); register(new LiquidMaskParser(worldEdit)); register(new RadiusMaskParser(worldEdit)); register(new RichOffsetMaskParser(worldEdit)); @@ -123,93 +115,36 @@ public final class MaskFactory extends AbstractFactory { register(new ZAxisMaskParser(worldEdit)); register(new SurfaceAngleMaskParser(worldEdit)); //FAWE end - } @Override - public List getSuggestions(String input) { + public List getSuggestions(String input, final ParserContext parserContext) { final String[] split = input.split(" "); if (split.length > 1) { String prev = input.substring(0, input.lastIndexOf(" ")) + " "; - return super.getSuggestions(split[split.length - 1]).stream().map(s -> prev + s).collect(Collectors.toList()); + return super + .getSuggestions(split[split.length - 1], parserContext) + .stream() + .map(s -> prev + s) + .collect(Collectors.toList()); } - return super.getSuggestions(input); - } - - @Override - public Mask parseFromInput(String input, ParserContext context) throws InputParseException { - List masks = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - //FAWE start - rich mask parsing - Mask match = richMaskParser.parseFromInput(component, context); - if (match != null) { - masks.add(match); - continue; - } - parseFromParsers(context, masks, component); - //FAWE end - } - - return getMask(input, masks); + return super.getSuggestions(input, parserContext); } //FAWE start - rich mask parsing - private void parseFromParsers( - final ParserContext context, - final List masks, - final String component - ) { - Mask match = null; - for (InputParser parser : getParsers()) { - match = parser.parseFromInput(component, context); - if (match != null) { - break; - } - } - if (match == null) { - throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component))); - } - masks.add(match); + @Override + public Mask parseFromInput(String input, ParserContext context) throws InputParseException { + return super.parseFromInput(input, context); } - /** - * Parses a mask without considering parsing through the {@link RichMaskParser}, therefore not accepting - * "richer" parsing where & and , are used. Exists to prevent stack overflows. - * - * @param input input string - * @param context input context - * @return parsed result - * @throws InputParseException if no result found - */ - public Mask parseWithoutRich(String input, ParserContext context) throws InputParseException { - List masks = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - parseFromParsers(context, masks, component); - } - - return getMask(input, masks); - } - - private Mask getMask(final String input, final List masks) { - switch (masks.size()) { - case 0: - throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); - case 1: - return masks.get(0).optimize(); - default: - return new MaskIntersection(masks).optimize(); - } + @Override + protected Mask getParsed(final String input, final List masks) { + return switch (masks.size()) { + case 0 -> throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); + case 1 -> masks.get(0).optimize(); + default -> new MaskIntersection(masks).optimize(); + }; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java index a76759833..242d1d7bc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java @@ -30,6 +30,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.DarkenPatter import com.fastasyncworldedit.core.extension.factory.parser.pattern.DesaturatePatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExpressionPatternParser; +import com.fastasyncworldedit.core.extension.factory.parser.pattern.HotbarPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.LightenPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser; @@ -42,8 +43,6 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.OffsetPatter import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomFullClipboardPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomOffsetPatternParser; -import com.fastasyncworldedit.core.extension.factory.parser.pattern.TypeSwapPatternParser; -import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser; @@ -51,11 +50,13 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.SaturatePatt import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.SolidRandomOffsetPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.SurfaceRandomOffsetPatternParser; +import com.fastasyncworldedit.core.extension.factory.parser.pattern.TypeSwapPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser; import com.fastasyncworldedit.core.math.random.TrueRandom; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser; @@ -65,10 +66,8 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.internal.registry.AbstractFactory; -import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.util.formatting.text.TextComponent; -import java.util.ArrayList; import java.util.List; /** @@ -80,20 +79,14 @@ import java.util.List; */ public final class PatternFactory extends AbstractFactory { - //FAWE start - rich pattern parsing - private final RichPatternParser richPatternParser; - //FAWE end - /** * Create a new instance. * * @param worldEdit the WorldEdit instance */ public PatternFactory(WorldEdit worldEdit) { - super(worldEdit, new SingleBlockPatternParser(worldEdit)); - //FAWE start - rich pattern parsing - richPatternParser = new RichPatternParser(worldEdit); + super(worldEdit, new SingleBlockPatternParser(worldEdit), new RichPatternParser(worldEdit)); //FAWE end // split and parse each sub-pattern @@ -116,6 +109,7 @@ public final class PatternFactory extends AbstractFactory { register(new DesaturatePatternParser(worldEdit)); register(new ExistingPatternParser(worldEdit)); register(new ExpressionPatternParser(worldEdit)); + register(new HotbarPatternParser(worldEdit)); register(new LightenPatternParser(worldEdit)); register(new Linear2DPatternParser(worldEdit)); register(new Linear3DPatternParser(worldEdit)); @@ -136,75 +130,17 @@ public final class PatternFactory extends AbstractFactory { register(new SurfaceRandomOffsetPatternParser(worldEdit)); register(new TypeSwapPatternParser(worldEdit)); register(new VoronoiPatternParser(worldEdit)); - //FAWE end - } - - @Override - public Pattern parseFromInput(String input, ParserContext context) throws InputParseException { - List patterns = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - //FAWE start - rich pattern parsing - Pattern match = richPatternParser.parseFromInput(component, context); - if (match != null) { - patterns.add(match); - continue; - } - parseFromParsers(context, patterns, component); - //FAWE end - } - - return getPattern(input, patterns); } //FAWE start - rich pattern parsing - private void parseFromParsers( - final ParserContext context, - final List patterns, - final String component - ) { - Pattern match = null; - for (InputParser parser : getParsers()) { - match = parser.parseFromInput(component, context); - if (match != null) { - break; - } - } - if (match == null) { - throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component))); - } - patterns.add(match); + @Override + public Pattern parseFromInput(String input, ParserContext context) throws InputParseException { + return super.parseFromInput(input, context); } - /** - * Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting - * "richer" parsing where & and , are used. Exists to prevent stack overflows. - * - * @param input input string - * @param context input context - * @return parsed result - * @throws InputParseException if no result found - */ - public Pattern parseWithoutRich(String input, ParserContext context) throws InputParseException { - List patterns = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - parseFromParsers(context, patterns, component); - } - - return getPattern(input, patterns); - } - - private Pattern getPattern(final String input, final List patterns) { + @Override + protected Pattern getParsed(final String input, final List patterns) { switch (patterns.size()) { case 0: throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index 0e70a18a6..7ef47de45 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -64,6 +64,7 @@ import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; +import javax.annotation.Nonnull; import java.util.Arrays; import java.util.HashMap; import java.util.Locale; @@ -134,42 +135,42 @@ public class DefaultBlockParser extends InputParser { private String woolMapper(String string) { switch (string.toLowerCase(Locale.ROOT)) { case "white": - return BlockTypes.WHITE_WOOL.getId(); + return BlockTypes.WHITE_WOOL.id(); case "black": - return BlockTypes.BLACK_WOOL.getId(); + return BlockTypes.BLACK_WOOL.id(); case "blue": - return BlockTypes.BLUE_WOOL.getId(); + return BlockTypes.BLUE_WOOL.id(); case "brown": - return BlockTypes.BROWN_WOOL.getId(); + return BlockTypes.BROWN_WOOL.id(); case "cyan": - return BlockTypes.CYAN_WOOL.getId(); + return BlockTypes.CYAN_WOOL.id(); case "gray": case "grey": - return BlockTypes.GRAY_WOOL.getId(); + return BlockTypes.GRAY_WOOL.id(); case "green": - return BlockTypes.GREEN_WOOL.getId(); + return BlockTypes.GREEN_WOOL.id(); case "light_blue": case "lightblue": - return BlockTypes.LIGHT_BLUE_WOOL.getId(); + return BlockTypes.LIGHT_BLUE_WOOL.id(); case "light_gray": case "light_grey": case "lightgray": case "lightgrey": - return BlockTypes.LIGHT_GRAY_WOOL.getId(); + return BlockTypes.LIGHT_GRAY_WOOL.id(); case "lime": - return BlockTypes.LIME_WOOL.getId(); + return BlockTypes.LIME_WOOL.id(); case "magenta": - return BlockTypes.MAGENTA_WOOL.getId(); + return BlockTypes.MAGENTA_WOOL.id(); case "orange": - return BlockTypes.ORANGE_WOOL.getId(); + return BlockTypes.ORANGE_WOOL.id(); case "pink": - return BlockTypes.PINK_WOOL.getId(); + return BlockTypes.PINK_WOOL.id(); case "purple": - return BlockTypes.PURPLE_WOOL.getId(); + return BlockTypes.PURPLE_WOOL.id(); case "yellow": - return BlockTypes.YELLOW_WOOL.getId(); + return BlockTypes.YELLOW_WOOL.id(); case "red": - return BlockTypes.RED_WOOL.getId(); + return BlockTypes.RED_WOOL.id(); default: return string; } @@ -193,7 +194,7 @@ public class DefaultBlockParser extends InputParser { if (input.indexOf('[') == -1 && input.indexOf(']') == -1) { continue; } - if (!type.getId().equalsIgnoreCase(input.substring(0, input.indexOf('[')))) { + if (!type.id().equalsIgnoreCase(input.substring(0, input.indexOf('[')))) { continue; } String[] properties = input.substring(input.indexOf('[') + 1, input.indexOf(']')).split(","); @@ -248,10 +249,10 @@ public class DefaultBlockParser extends InputParser { throw new NoMatchException(Caption.of( "worldedit.error.parser.unknown-property", TextComponent.of(parts[0]), - TextComponent.of(type.getId()) + TextComponent.of(type.id()) )); } else { - WorldEdit.logger.debug("Unknown property " + parts[0] + " for block " + type.getId()); + WorldEdit.logger.debug("Unknown property " + parts[0] + " for block " + type.id()); } return Maps.newHashMap(); } @@ -337,9 +338,10 @@ public class DefaultBlockParser extends InputParser { return SuggestionHelper.getBlockPropertySuggestions(blockType, props); } + @Nonnull private BaseBlock parseLogic(String input, ParserContext context) throws InputParseException { //FAWE start - String[] blockAndExtraData = input.trim().split("\\|"); + String[] blockAndExtraData = input.trim().split("(?, Object> blockStates = new HashMap<>(); //FAWE end @@ -463,6 +465,7 @@ public class DefaultBlockParser extends InputParser { if (state == null) { throw new NoMatchException(Caption.of("fawe.error.invalid-block-type", TextComponent.of(input))); } + nbt = state.getNbtData(); } //FAWE end @@ -514,20 +517,20 @@ public class DefaultBlockParser extends InputParser { //FAWE start - per-limit disallowed blocks if (actor != null) { if (!actor.hasPermission("worldedit.anyblock") - && worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId().toLowerCase(Locale.ROOT))) { + && worldEdit.getConfiguration().disallowedBlocks.contains(blockType.id().toLowerCase(Locale.ROOT))) { throw new DisallowedUsageException(Caption.of( "worldedit.error.disallowed-block", - TextComponent.of(blockType.getId()) + TextComponent.of(blockType.id()) )); } FaweLimit limit = actor.getLimit(); if (!limit.isUnlimited()) { // No need to account for blocked states/properties as it will simply return false in the equality check // during contains. - if (limit.DISALLOWED_BLOCKS.contains(blockType.getId().toLowerCase(Locale.ROOT))) { + if (limit.DISALLOWED_BLOCKS.contains(blockType.id().toLowerCase(Locale.ROOT))) { throw new DisallowedUsageException(Caption.of( "fawe.error.limit.disallowed-block", - TextComponent.of(blockType.getId()) + TextComponent.of(blockType.id()) )); } } @@ -557,14 +560,14 @@ public class DefaultBlockParser extends InputParser { if (ent == null) { throw new NoMatchException(Caption.of("worldedit.error.unknown-entity", TextComponent.of(mobName))); } - mobName = ent.getId(); + mobName = ent.id(); if (!worldEdit.getPlatformManager().queryCapability(Capability.USER_COMMANDS).isValidMobType(mobName)) { throw new NoMatchException(Caption.of("worldedit.error.unknown-mob", TextComponent.of(mobName))); } return validate(context, new MobSpawnerBlock(state, mobName)); } else { //noinspection ConstantConditions - return validate(context, new MobSpawnerBlock(state, EntityTypes.PIG.getId())); + return validate(context, new MobSpawnerBlock(state, EntityTypes.PIG.id())); } } else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) { // allow setting type/player/rotation diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java index b889d4dca..2eb4fbfe3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.extension.factory.parser; import com.fastasyncworldedit.core.configuration.Caption; -import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; @@ -35,13 +34,13 @@ import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.TagStringIO; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; +import org.enginehub.linbus.format.snbt.LinStringIO; +import org.enginehub.linbus.stream.exception.NbtParseException; +import org.enginehub.linbus.tree.LinCompoundTag; -import java.io.IOException; import java.util.Locale; import java.util.stream.Stream; @@ -59,7 +58,7 @@ public class DefaultItemParser extends InputParser { @Override public BaseItem parseFromInput(String input, ParserContext context) throws InputParseException { ItemType itemType; - CompoundBinaryTag itemNbtData = null; + LinCompoundTag itemNbtData = null; BaseItem item = null; @@ -128,20 +127,21 @@ public class DefaultItemParser extends InputParser { } if (nbtString != null) { + LinCompoundTag otherTag; try { - CompoundBinaryTag otherTag = TagStringIO.get().asCompound(nbtString); - if (itemNbtData == null) { - itemNbtData = otherTag; - } else { - itemNbtData.put(NbtUtils.getCompoundBinaryTagValues(otherTag)); - } - } catch (IOException e) { + otherTag = LinStringIO.readFromStringUsing(nbtString, LinCompoundTag::readFrom); + } catch (NbtParseException e) { throw new NoMatchException(TranslatableComponent.of( "worldedit.error.invalid-nbt", TextComponent.of(input), TextComponent.of(e.getMessage()) )); } + if (itemNbtData == null) { + itemNbtData = otherTag; + } else { + itemNbtData = itemNbtData.toBuilder().putAll(otherTag.value()).build(); + } } item = new BaseItem(itemType, itemNbtData == null ? null : LazyReference.computed(itemNbtData)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java index de6eea718..ac94b12d4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java @@ -49,6 +49,7 @@ public class BlocksMaskParser extends InputParser { ParserContext tempContext = new ParserContext(context); tempContext.setRestricted(false); tempContext.setPreferringWildcard(true); + tempContext.setTryLegacy(context.isTryingLegacy()); try { Set holders = worldEdit.getBlockFactory().parseFromListInput(component, tempContext); if (holders.isEmpty()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BlockCategoryPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BlockCategoryPatternParser.java index 36d83eb37..089f2d861 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BlockCategoryPatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BlockCategoryPatternParser.java @@ -71,7 +71,7 @@ public class BlockCategoryPatternParser extends InputParser implements Set blocks = category.getAll(); if (blocks.isEmpty()) { - throw new InputParseException(Caption.of("worldedit.error.empty-tag", TextComponent.of(category.getId()))); + throw new InputParseException(Caption.of("worldedit.error.empty-tag", TextComponent.of(category.id()))); } if (anyState) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java index 430280814..989931b0b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java @@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.factory.MaskFactory; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; @@ -217,6 +218,20 @@ public class ParserContext { return actor; } + /** + * Get the {@link Player} set on this context. + * + * @return a player + * @throws InputParseException thrown if no {@link Actor} is set + */ + public Player requirePlayer() throws InputParseException { + Actor actor = getActor(); + if (!(actor instanceof Player player)) { + throw new InputParseException(Caption.of("worldedit.error.missing-player")); + } + return player; + } + /** * Returns whether there should be restrictions (as a result of * limits or permissions) considered when parsing the input. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlatform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlatform.java index 533fe054d..c8f908b4c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlatform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlatform.java @@ -55,4 +55,9 @@ public abstract class AbstractPlatform implements Platform { return null; } + @Override + public long getTickCount() { + return System.nanoTime() / 50_000_000; + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index ae4eb2144..23b3799ef 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -19,10 +19,14 @@ package com.sk89q.worldedit.extension.platform; +import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismatchException; import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.regions.FaweMaskManager; +import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.WEManager; import com.fastasyncworldedit.core.util.task.AsyncNotifyKeyedQueue; @@ -34,6 +38,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.cui.CUIEvent; +import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; @@ -62,11 +67,14 @@ import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; +import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.io.File; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; /** @@ -76,8 +84,11 @@ import java.util.concurrent.atomic.AtomicInteger; */ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { + private static final Logger LOGGER = LogManagerCompat.getLogger(); + //FAWE start private final Map meta; + private final Semaphore clipboardLoading = new Semaphore(1); // Queue for async tasks private final AtomicInteger runningCount = new AtomicInteger(); @@ -93,7 +104,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { if (fe != null) { printError(fe.getComponent()); } else { - throwable.printStackTrace(); + LOGGER.error("Error occurred executing player action", throwable); } } }, this::getUniqueId); @@ -162,8 +173,8 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { public void findFreePosition(Location searchPos) { Extent world = searchPos.getExtent(); - int worldMinY = world.getMinimumPoint().getY(); - int worldMaxY = world.getMaximumPoint().getY(); + int worldMinY = world.getMinimumPoint().y(); + int worldMaxY = world.getMaximumPoint().y(); int x = searchPos.getBlockX(); int y = Math.max(worldMinY, searchPos.getBlockY()); @@ -202,7 +213,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { public void setOnGround(Location searchPos) { Extent world = searchPos.getExtent(); - int worldMinY = world.getMinimumPoint().getY(); + int worldMinY = world.getMinimumPoint().y(); int x = searchPos.getBlockX(); int y = Math.max(worldMinY, searchPos.getBlockY()); @@ -436,7 +447,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { @Override public Location getBlockOn() { final Location location = getLocation(); - return location.setPosition(location.setY(location.getY() - 1).toVector().floor()); + return location.setPosition(location.setY(location.y() - 1).toVector().floor()); } @Override @@ -520,22 +531,68 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { @Override public void setSelection(Region region) { - RegionSelector selector; - if (region instanceof ConvexPolyhedralRegion) { - selector = new ConvexPolyhedralRegionSelector((ConvexPolyhedralRegion) region); - } else if (region instanceof CylinderRegion) { - selector = new CylinderRegionSelector((CylinderRegion) region); - } else if (region instanceof Polygonal2DRegion) { - selector = new Polygonal2DRegionSelector((Polygonal2DRegion) region); - } else { - selector = new CuboidRegionSelector(null, region.getMinimumPoint(), - region.getMaximumPoint() - ); - } + RegionSelector selector = switch (region) { + case ConvexPolyhedralRegion blockVector3s -> new ConvexPolyhedralRegionSelector(blockVector3s); + case CylinderRegion blockVector3s -> new CylinderRegionSelector(blockVector3s); + case Polygonal2DRegion blockVector3s -> new Polygonal2DRegionSelector(blockVector3s); + default -> new CuboidRegionSelector(null, region.getMinimumPoint(), region.getMaximumPoint()); + }; selector.setWorld(region.getWorld()); getSession().setRegionSelector(getWorld(), selector); } + + @Override + public void loadClipboardFromDisk() { + if (!clipboardLoading.tryAcquire()) { + if (!Fawe.isMainThread()) { + try { + clipboardLoading.acquire(); + clipboardLoading.release(); + } catch (InterruptedException e) { + LOGGER.error("Error waiting for clipboard-on-disk loading for player {}", getName(), e); + } + } + return; + } + + File file = MainUtil.getFile( + Fawe.platform().getDirectory(), + Settings.settings().PATHS.CLIPBOARD + File.separator + getUniqueId() + ".bd" + ); + try { + Future fut = Fawe.instance().submitUUIDKeyQueuedTask(getUniqueId(), () -> { + try { + getSession().loadClipboardFromDisk(file); + } catch (FaweClipboardVersionMismatchException e) { + print(e.getComponent()); + } catch (RuntimeException e) { + print(Caption.of("fawe.error.clipboard.invalid")); + LOGGER.error("Error loading clipboard from disk", e); + print(Caption.of("fawe.error.stacktrace")); + print(Caption.of("fawe.error.clipboard.load.failure")); + print(Caption.of("fawe.error.clipboard.invalid.info", file.getName(), file.length())); + print(Caption.of("fawe.error.stacktrace")); + } catch (Exception e) { + print(Caption.of("fawe.error.clipboard.invalid")); + LOGGER.error("Error loading clipboard from disk", e); + print(Caption.of("fawe.error.stacktrace")); + print(Caption.of("fawe.error.no-failure")); + print(Caption.of("fawe.error.clipboard.invalid.info", file.getName(), file.length())); + print(Caption.of("fawe.error.stacktrace")); + } finally { + clipboardLoading.release(); + } + }); + if (Fawe.isMainThread()) { + return; + } + fut.get(); + } catch (Exception e) { + LOGGER.error("Error loading clipboard from disk", e); + print(Caption.of("fawe.error.clipboard.load.failure")); + } + } //FAWE end @Override @@ -694,10 +751,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { @Override public boolean equals(Object other) { - if (!(other instanceof Player)) { + if (!(other instanceof Player other2)) { return false; } - Player other2 = (Player) other; return other2.getName().equals(getName()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java index 822e7a3f8..472dce93c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java @@ -216,6 +216,14 @@ public interface Platform extends Keyed { */ Set getSupportedSideEffects(); + /** + * Get the number of ticks since the server started. + * On some platforms this value may be an approximation based on the JVM run time. + * + * @return The number of ticks since the server started. + */ + long getTickCount(); + //FAWE start /** @@ -225,7 +233,7 @@ public interface Platform extends Keyed { */ @NonAbstractForCompatibility(delegateName = "getPlatformName", delegateParams = {}) @Override - default String getId() { + default String id() { return "legacy:" + getPlatformName().toLowerCase(Locale.ROOT).replaceAll("[^a-z_.-]", "_"); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index e84a240f0..f85ddc8ee 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -24,6 +24,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extension.platform.binding.Bindings; import com.fastasyncworldedit.core.extension.platform.binding.ConsumeBindings; +import com.fastasyncworldedit.core.extension.platform.binding.EditSessionHolder; import com.fastasyncworldedit.core.extension.platform.binding.PrimitiveBindings; import com.fastasyncworldedit.core.extension.platform.binding.ProvideBindings; import com.fastasyncworldedit.core.internal.command.MethodInjector; @@ -86,6 +87,8 @@ import com.sk89q.worldedit.command.WorldEditCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.Chunk3dVectorConverter; +import com.sk89q.worldedit.command.argument.ClipboardFormatConverter; +import com.sk89q.worldedit.command.argument.ClipboardShareDestinationConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; import com.sk89q.worldedit.command.argument.DirectionVectorConverter; @@ -152,7 +155,6 @@ import org.enginehub.piston.inject.MemoizingValueAccess; import org.enginehub.piston.inject.MergedValueAccess; import org.enginehub.piston.part.SubCommandPart; import org.enginehub.piston.suggestion.Suggestion; -import org.enginehub.piston.util.HelpGenerator; import org.enginehub.piston.util.ValueProvider; import javax.annotation.Nonnull; @@ -174,7 +176,6 @@ import java.util.stream.Stream; import static com.google.common.base.Preconditions.checkNotNull; - /** * Handles the registration and invocation of commands. * @@ -226,7 +227,6 @@ public final class PlatformCommandManager { new ConfirmHandler(), new PreloadHandler() //FAWE end - )); // setup separate from main constructor // ensures that everything is definitely assigned @@ -272,6 +272,8 @@ public final class PlatformCommandManager { SideEffectConverter.register(commandManager); HeightConverter.register(commandManager); OffsetConverter.register(worldEdit, commandManager); + ClipboardFormatConverter.register(commandManager); + ClipboardShareDestinationConverter.register(commandManager); //FAWE start commandManager.registerConverter( Key.of(com.sk89q.worldedit.function.pattern.Pattern.class, Annotations.patternList()), @@ -309,20 +311,6 @@ public final class PlatformCommandManager { } ); //FAWE start - /* - globalInjectedValues.injectValue(Key.of(EditSession.class), - context -> { - LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) - .orElseThrow(() -> new IllegalStateException("No LocalSession")); - return context.injectedValue(Key.of(Actor.class)) - .map(actor -> { - EditSession editSession = localSession.createEditSession(actor); - editSession.enableStandardMode(); - Request.request().setEditSession(editSession); - return editSession; - }); - }); - */ // TODO: Ping @MattBDev to reimplement 2020-02-04 // globalInjectedValues.injectValue(Key.of(CFICommands.CFISettings.class), // context -> context.injectedValue(Key.of(Actor.class)) @@ -604,7 +592,6 @@ public final class PlatformCommandManager { void registerCommandsWith(Platform platform) { LOGGER.info("Registering commands with " + platform.getClass().getCanonicalName()); - LocalConfiguration config = platform.getConfiguration(); boolean logging = config.logCommands; String path = config.logFile; @@ -864,10 +851,10 @@ public final class PlatformCommandManager { store.injectValue(Key.of(InjectedValueStore.class), ValueProvider.constant(store)); store.injectValue(Key.of(Event.class), ValueProvider.constant(event)); //FAWE start - allow giving editsessions - if (event instanceof CommandEvent) { - EditSession session = ((CommandEvent) event).getSession(); + if (event instanceof CommandEvent commandEvent) { + EditSession session = commandEvent.getSession(); if (session != null) { - store.injectValue(Key.of(EditSession.class), context -> Optional.of(session)); + store.injectValue(Key.of(EditSessionHolder.class), context -> Optional.of(new EditSessionHolder(session))); } } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 9f798e21c..72feee18d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -273,9 +273,7 @@ public class PlatformManager { public T createProxyActor(T base) { checkNotNull(base); - if (base instanceof Player) { - Player player = (Player) base; - + if (base instanceof Player player) { Player permActor = queryCapability(Capability.PERMISSIONS).matchPlayer(player); if (permActor == null) { permActor = player; @@ -389,10 +387,9 @@ public class PlatformManager { Location location = event.getLocation(); // At this time, only handle interaction from players - if (!(actor instanceof Player)) { + if (!(actor instanceof Player player)) { return; } - Player player = (Player) actor; LocalSession session = worldEdit.getSessionManager().get(actor); Request.reset(); @@ -463,7 +460,7 @@ public class PlatformManager { } else { actor.print(Caption.of("worldedit.command.error.report")); actor.print(TextComponent.of(e.getClass().getName()+ ": " + e.getMessage())); - e.printStackTrace(); + LOGGER.error("Error occurred executing player action", e); } } //FAWE end @@ -511,14 +508,7 @@ public class PlatformManager { } //FAWE start - add own message } catch (Throwable e) { - FaweException faweException = FaweException.get(e); - if (faweException != null) { - player.print(Caption.of("fawe.cancel.reason", faweException.getComponent())); - } else { - player.print(Caption.of("worldedit.command.error.report")); - player.print(TextComponent.of(e.getClass().getName() + ": " + e.getMessage())); - e.printStackTrace(); - } + handleThrowable(e, player); //FAWE end } finally { Request.reset(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index 9dfd373ea..89c450a10 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -25,27 +25,35 @@ import com.fastasyncworldedit.core.extent.HistoryExtent; import com.fastasyncworldedit.core.extent.NullExtent; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.util.ExtentTraverser; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.OperationQueue; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.List; +import java.util.Set; import java.util.UUID; import static com.google.common.base.Preconditions.checkNotNull; @@ -84,9 +92,7 @@ public class AbstractDelegateExtent implements Extent { @Override public BlockState getBlock(BlockVector3 position) { - //FAWE start - return coordinates - return extent.getBlock(position.getX(), position.getY(), position.getZ()); - //FAWE end + return extent.getBlock(position); } @Override @@ -96,9 +102,7 @@ public class AbstractDelegateExtent implements Extent { @Override public BaseBlock getFullBlock(BlockVector3 position) { - //FAWE start - return coordinates - return extent.getFullBlock(position.getX(), position.getY(), position.getZ()); - //FAWE end + return extent.getFullBlock(position); } //FAWE start @@ -110,9 +114,7 @@ public class AbstractDelegateExtent implements Extent { @Override public BaseBlock getFullBlock(int x, int y, int z) { - //FAWE start - return coordinates return extent.getFullBlock(x, y, z); - //FAWE end } @Override @@ -168,6 +170,7 @@ public class AbstractDelegateExtent implements Extent { } } + //FAWE start @Override public boolean cancel() { ExtentTraverser traverser = new ExtentTraverser<>(this); @@ -188,7 +191,6 @@ public class AbstractDelegateExtent implements Extent { return true; } - //FAWE start @Override public void removeEntity(int x, int y, int z, UUID uuid) { extent.removeEntity(x, y, z, uuid); @@ -225,11 +227,72 @@ public class AbstractDelegateExtent implements Extent { } } + @Override + public boolean isWorld() { + return extent.isWorld(); + } + + @Override + public List> getBlockDistribution(final Region region) { + return extent.getBlockDistribution(region); + } + + @Override + public List> getBlockDistributionWithData(final Region region) { + return extent.getBlockDistributionWithData(region); + } + @Override public int getMaxY() { return extent.getMaxY(); } + @Override + public int countBlocks(final Region region, final Set searchBlocks) { + return extent.countBlocks(region, searchBlocks); + } + + @Override + public int countBlocks(final Region region, final Mask searchMask) { + return extent.countBlocks(region, searchMask); + } + + @Override + public > int setBlocks(final Region region, final B block) throws MaxChangedBlocksException { + return extent.setBlocks(region, block); + } + + @Override + public int setBlocks(final Region region, final Pattern pattern) throws MaxChangedBlocksException { + return extent.setBlocks(region, pattern); + } + + @Override + public > int replaceBlocks( + final Region region, + final Set filter, + final B replacement + ) + throws MaxChangedBlocksException { + return extent.replaceBlocks(region, filter, replacement); + } + + @Override + public int replaceBlocks(final Region region, final Set filter, final Pattern pattern) throws + MaxChangedBlocksException { + return extent.replaceBlocks(region, filter, pattern); + } + + @Override + public int replaceBlocks(final Region region, final Mask mask, final Pattern pattern) throws MaxChangedBlocksException { + return extent.replaceBlocks(region, mask, pattern); + } + + @Override + public int setBlocks(final Set vset, final Pattern pattern) { + return extent.setBlocks(vset, pattern); + } + @Override public int getMinY() { return extent.getMinY(); @@ -295,22 +358,26 @@ public class AbstractDelegateExtent implements Extent { return this; } + @Override + public T apply(final Region region, final T filter, final boolean full) { + return extent.apply(region, filter, full); + } + //FAWE end + protected Operation commitBefore() { return null; } - @Override - public BiomeType getBiomeType(int x, int y, int z) { - return extent.getBiomeType(x, y, z); - } - @Override public BiomeType getBiome(BlockVector3 position) { return extent.getBiome(position); } - /* - History - */ + + //FAWE start + @Override + public BiomeType getBiomeType(int x, int y, int z) { + return extent.getBiomeType(x, y, z); + } @Override public int getEmittedLight(int x, int y, int z) { @@ -341,13 +408,15 @@ public class AbstractDelegateExtent implements Extent { new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet)); } } + //FAWE end @Override public > boolean setBlock(BlockVector3 position, T block) throws WorldEditException { - return extent.setBlock(position.getX(), position.getY(), position.getZ(), block); + return extent.setBlock(position, block); } + //FAWE start @Override public > boolean setBlock( int x, int y, @@ -357,9 +426,10 @@ public class AbstractDelegateExtent implements Extent { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile)); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile == null ? null : tile.linTag())); } + //FAWE end @Override public boolean fullySupports3DBiomes() { @@ -367,13 +437,14 @@ public class AbstractDelegateExtent implements Extent { } @Override - public boolean setBiome(int x, int y, int z, BiomeType biome) { - return extent.setBiome(x, y, z, biome); + public boolean setBiome(BlockVector3 position, BiomeType biome) { + return extent.setBiome(position, biome); } + //FAWE start @Override - public boolean setBiome(BlockVector3 position, BiomeType biome) { - return extent.setBiome(position.getX(), position.getY(), position.getZ(), biome); + public boolean setBiome(int x, int y, int z, BiomeType biome) { + return extent.setBiome(x, y, z, biome); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 3d2a45642..9f73c8f5e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -216,7 +216,7 @@ public interface Extent extends InputExtent, OutputExtent { */ /** - * Returns the highest solid 'terrain' block. + * Returns the highest solid 'terrain' (movement-blocking) block. * * @param x the X coordinate * @param z the Z coordinate @@ -225,6 +225,9 @@ public interface Extent extends InputExtent, OutputExtent { * @return height of highest block found or 'minY' */ default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) { + maxY = Math.min(maxY, getMaxY()); + minY = Math.max(getMinY(), minY); + for (int y = maxY; y >= minY; --y) { BlockState block = getBlock(x, y, z); if (block.getBlockType().getMaterial().isMovementBlocker()) { @@ -235,7 +238,7 @@ public interface Extent extends InputExtent, OutputExtent { } /** - * Returns the highest solid 'terrain' block. + * Returns the highest block matching the given mask. * * @param x the X coordinate * @param z the Z coordinate @@ -245,6 +248,9 @@ public interface Extent extends InputExtent, OutputExtent { * @return height of highest block found or 'minY' */ default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY, Mask filter) { + if (filter == null) { + return getHighestTerrainBlock(x, z, minY, maxY); + } maxY = Math.min(maxY, getMaxY()); minY = Math.max(getMinY(), minY); @@ -259,9 +265,7 @@ public interface Extent extends InputExtent, OutputExtent { } /** - * Returns the nearest surface layer (up/down from start) - *

- * TODO: Someone understand this..? + * Returns the nearest surface layer (up/down from start), where a layer is 1/16th of a block to allow for snow, liquid, etc. * * @param x x to search from * @param z y to search from @@ -271,6 +275,9 @@ public interface Extent extends InputExtent, OutputExtent { * @return nearest surface layer */ default int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { + maxY = Math.min(maxY, getMaxY()); + minY = Math.max(getMinY(), minY); + int clearanceAbove = maxY - y; int clearanceBelow = y - minY; int clearance = Math.min(clearanceAbove, clearanceBelow); @@ -331,6 +338,9 @@ public interface Extent extends InputExtent, OutputExtent { * @return The y value of the nearest terrain block */ default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) { + maxY = Math.min(maxY, getMaxY()); + minY = Math.max(getMinY(), minY); + y = Math.max(minY, Math.min(maxY, y)); int clearanceAbove = maxY - y; int clearanceBelow = y - minY; @@ -438,6 +448,9 @@ public interface Extent extends InputExtent, OutputExtent { int failedMax, boolean ignoreAir ) { + maxY = Math.min(maxY, getMaxY()); + minY = Math.max(getMinY(), minY); + y = Math.max(minY, Math.min(maxY, y)); int clearanceAbove = maxY - y; int clearanceBelow = y - minY; @@ -494,7 +507,7 @@ public interface Extent extends InputExtent, OutputExtent { default void addSchems(Region region, Mask mask, List clipboards, int rarity, boolean rotate) throws WorldEditException { - spawnResource(region, new SchemGen(mask, this, clipboards, rotate), rarity, 1); + spawnResource(region, new SchemGen(mask, this, clipboards, rotate, region), rarity, 1); } default void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException { @@ -504,8 +517,8 @@ public interface Extent extends InputExtent, OutputExtent { if (random.nextInt(100) > rarity) { continue; } - int x = (chunkPos.getBlockX() << 4) + random.nextInt(16); - int z = (chunkPos.getBlockZ() << 4) + random.nextInt(16); + int x = (chunkPos.x() << 4) + random.nextInt(16); + int z = (chunkPos.z() << 4) + random.nextInt(16); gen.spawn(random, x, z); } } @@ -534,9 +547,9 @@ public interface Extent extends InputExtent, OutputExtent { default boolean contains(int x, int y, int z) { BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return min.getX() <= x && max.getX() >= x - && min.getY() <= y && max.getY() >= y - && min.getZ() <= z && max.getZ() >= z; + return min.x() <= x && max.x() >= x + && min.y() <= y && max.y() >= y + && min.z() <= z && max.z() >= z; } default void addOre( @@ -665,11 +678,11 @@ public interface Extent extends InputExtent, OutputExtent { } default int getMinY() { - return getMinimumPoint().getY(); + return getMinimumPoint().y(); } default int getMaxY() { - return getMaximumPoint().getY(); + return getMaximumPoint().y(); } /** @@ -723,7 +736,6 @@ public interface Extent extends InputExtent, OutputExtent { default > int setBlocks(Region region, B block) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(block); - boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); int changes = 0; for (BlockVector3 pos : region) { @@ -832,9 +844,9 @@ public interface Extent extends InputExtent, OutputExtent { Vector3 center = region.getCenter(); Region centerRegion = new CuboidRegion( this instanceof World ? (World) this : null, // Causes clamping of Y range - BlockVector3.at(((int) center.getX()), ((int) center.getY()), ((int) center.getZ())), - BlockVector3.at(MathUtils.roundHalfUp(center.getX()), - center.getY(), MathUtils.roundHalfUp(center.getZ()) + BlockVector3.at(((int) center.x()), ((int) center.y()), ((int) center.z())), + BlockVector3.at(MathUtils.roundHalfUp(center.x()), + center.y(), MathUtils.roundHalfUp(center.z()) ) ); return setBlocks(centerRegion, pattern); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java index 58863920c..7393c7722 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java @@ -50,7 +50,7 @@ public interface InputExtent { * @return the block */ default BlockState getBlock(BlockVector3 position) { - return getBlock(position.getX(), position.getY(), position.getZ()); + return getBlock(position.x(), position.y(), position.z()); } //FAWE start @@ -65,7 +65,7 @@ public interface InputExtent { * @return the block */ default BaseBlock getFullBlock(BlockVector3 position) { - return getFullBlock(position.getX(), position.getY(), position.getZ()); + return getFullBlock(position.x(), position.y(), position.z()); } default BaseBlock getFullBlock(int x, int y, int z) { @@ -85,7 +85,7 @@ public interface InputExtent { */ @Deprecated default BiomeType getBiome(BlockVector2 position) { - return getBiomeType(position.getX(), 0, position.getZ()); + return getBiomeType(position.x(), 0, position.z()); } default BiomeType getBiomeType(int x, int y, int z) { @@ -126,7 +126,7 @@ public interface InputExtent { * @return the light level at the location */ default int getEmittedLight(BlockVector3 position) { - return getEmittedLight(position.getX(), position.getY(), position.getZ()); + return getEmittedLight(position.x(), position.y(), position.z()); } default int getEmittedLight(int x, int y, int z) { @@ -140,7 +140,7 @@ public interface InputExtent { * @return the sky light level at the location */ default int getSkyLight(MutableBlockVector3 position) { - return getSkyLight(position.getX(), position.getY(), position.getZ()); + return getSkyLight(position.x(), position.y(), position.z()); } default int getSkyLight(int x, int y, int z) { @@ -148,7 +148,7 @@ public interface InputExtent { } default int getBrightness(MutableBlockVector3 position) { - return getBrightness(position.getX(), position.getY(), position.getZ()); + return getBrightness(position.x(), position.y(), position.z()); } default int getBrightness(int x, int y, int z) { @@ -156,7 +156,7 @@ public interface InputExtent { } default int getOpacity(MutableBlockVector3 position) { - return getOpacity(position.getX(), position.getY(), position.getZ()); + return getOpacity(position.x(), position.y(), position.z()); } default int getOpacity(int x, int y, int z) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java index 64b6eecc3..77f9aa1c7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java @@ -24,6 +24,8 @@ import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; @@ -35,6 +37,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; +import javax.annotation.Nullable; import java.util.function.LongFunction; import static com.google.common.base.Preconditions.checkNotNull; @@ -47,6 +50,7 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce //FAWE start private final LongFunction getOrCreateFilterBlock; private Mask mask; + private @Nullable VectorizedMask vectorizedMask; //FAWE end /** @@ -59,16 +63,23 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce super(extent); checkNotNull(mask); this.mask = mask; + this.vectorizedMask = SimdSupport.vectorizedTargetMask(mask); //FAWE start this.getOrCreateFilterBlock = FaweCache.INSTANCE.createMainThreadSafeCache(() -> new CharFilterBlock(getExtent())); //FAWE end } //FAWE start - private MaskingExtent(Extent extent, Mask mask, LongFunction getOrCreateFilterBlock) { + private MaskingExtent( + Extent extent, + Mask mask, + LongFunction getOrCreateFilterBlock, + @Nullable VectorizedMask vectorizedMask + ) { super(extent); checkNotNull(mask); this.mask = mask; + this.vectorizedMask = vectorizedMask; this.getOrCreateFilterBlock = getOrCreateFilterBlock; } //FAWE end @@ -90,6 +101,7 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce public void setMask(Mask mask) { checkNotNull(mask); this.mask = mask; + this.vectorizedMask = SimdSupport.vectorizedTargetMask(mask); } //FAWE start @@ -105,8 +117,13 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce @Override public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + if (this.vectorizedMask != null) { + this.vectorizedMask.processChunks(chunk, get, set); + return set; + } final ChunkFilterBlock filter = getOrCreateFilterBlock.apply(Thread.currentThread().getId()); - return filter.filter(chunk, get, set, MaskingExtent.this); + filter.initChunk(chunk.getX(), chunk.getZ()); + return filter.filter(chunk, get, set, this); } @Override @@ -121,12 +138,12 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce if (child == getExtent()) { return this; } - return new MaskingExtent(child, this.mask.copy(), this.getOrCreateFilterBlock); + return new MaskingExtent(child, this.mask.copy(), this.getOrCreateFilterBlock, this.vectorizedMask); } @Override public Filter fork() { - return new MaskingExtent(getExtent(), this.mask.copy(), this.getOrCreateFilterBlock); + return new MaskingExtent(getExtent(), this.mask.copy(), this.getOrCreateFilterBlock, this.vectorizedMask); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java index 934b52204..b98e0f4b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java @@ -19,8 +19,8 @@ package com.sk89q.worldedit.extent; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -108,7 +108,7 @@ public class NullExtent implements Extent { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java index d90bce937..b38e2dc2d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.extent; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -60,7 +61,7 @@ public interface OutputExtent { */ @Deprecated default > boolean setBlock(BlockVector3 position, T block) throws WorldEditException { - return setBlock(position.getX(), position.getY(), position.getZ(), block); + return setBlock(position.x(), position.y(), position.z(), block); } // The defaults need to remain for compatibility (the actual implementation still needs to override one of these) @@ -68,7 +69,24 @@ public interface OutputExtent { return setBlock(MutableBlockVector3.get(x, y, z), block); } - boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException; + /** + * @deprecated use {@link #tile(int, int, int, FaweCompoundTag)} instead + */ + @Deprecated(forRemoval = true, since = "2.11.2") + default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); + } + + /** + * Sets a tile/block entity at the given location. + * @param x the x position + * @param y the y position + * @param z the z position + * @param tile the tile/block entity to set + * @return {@code true} if the tile/block entity was placed + * @since 2.11.2 + */ + boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException; /** * Check if this extent fully supports 3D biomes. @@ -148,7 +166,7 @@ public interface OutputExtent { * @param value light level to set */ default void setBlockLight(BlockVector3 position, int value) { - setBlockLight(position.getX(), position.getY(), position.getZ(), value); + setBlockLight(position.x(), position.y(), position.z(), value); } default void setBlockLight(int x, int y, int z, int value) { @@ -161,7 +179,7 @@ public interface OutputExtent { * @param value light level to set */ default void setSkyLight(BlockVector3 position, int value) { - setSkyLight(position.getX(), position.getY(), position.getZ(), value); + setSkyLight(position.x(), position.y(), position.z(), value); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ForgetfulExtentBuffer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ForgetfulExtentBuffer.java index f569acd00..ca2bfd965 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ForgetfulExtentBuffer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ForgetfulExtentBuffer.java @@ -235,4 +235,11 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat }; } + //FAWE - stateful pattern + @Override + public Pattern fork() { + return new ForgetfulExtentBuffer(extent, mask.copy()); + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java index 7b6be41d2..9ff666f79 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java @@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.extent.clipboard.SimpleClipboard; import com.fastasyncworldedit.core.function.visitor.Order; import com.fastasyncworldedit.core.math.MutableBlockVector2; import com.fastasyncworldedit.core.math.OffsetBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.google.common.collect.Iterators; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; @@ -165,9 +166,9 @@ public class BlockArrayClipboard implements Clipboard { @Override public BlockState getBlock(BlockVector3 position) { if (region.contains(position)) { - int x = position.getBlockX() - offset.getX(); - int y = position.getBlockY() - offset.getY(); - int z = position.getBlockZ() - offset.getZ(); + int x = position.x() - offset.x(); + int y = position.y() - offset.y(); + int z = position.z() - offset.z(); return getParent().getBlock(x, y, z); } @@ -177,21 +178,21 @@ public class BlockArrayClipboard implements Clipboard { @Override public BaseBlock getFullBlock(BlockVector3 position) { if (region.contains(position)) { - int x = position.getBlockX() - offset.getX(); - int y = position.getBlockY() - offset.getY(); - int z = position.getBlockZ() - offset.getZ(); + int x = position.x() - offset.x(); + int y = position.y() - offset.y(); + int z = position.z() - offset.z(); return getParent().getFullBlock(x, y, z); } return BlockTypes.AIR.getDefaultState().toBaseBlock(); } @Override - public > boolean setBlock(BlockVector3 position, B block) throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block) { if (region.contains(position)) { //FAWE - get points - final int x = position.getBlockX(); - final int y = position.getBlockY(); - final int z = position.getBlockZ(); + final int x = position.x(); + final int y = position.y(); + final int z = position.z(); return setBlock(x, y, z, block); //FAWE end } @@ -200,23 +201,24 @@ public class BlockArrayClipboard implements Clipboard { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); - return getParent().setTile(x, y, z, tag); + public boolean tile(int x, int y, int z, FaweCompoundTag tag) { + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); + return getParent().tile(x, y, z, tag); } + @Deprecated(forRemoval = true, since = "2.11.2") public boolean setTile(BlockVector3 position, CompoundTag tag) { - return setTile(position.getX(), position.getY(), position.getZ(), tag); + return tile(position.x(), position.y(), position.z(), FaweCompoundTag.of(tag.toLinTag())); } @Override public > boolean setBlock(int x, int y, int z, B block) throws WorldEditException { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); return parent.setBlock(x, y, z, block); } @@ -230,25 +232,25 @@ public class BlockArrayClipboard implements Clipboard { if (!region.contains(position)) { return null; } - int x = position.getBlockX() - offset.getX(); - int y = position.getBlockY() - offset.getY(); - int z = position.getBlockZ() - offset.getZ(); + int x = position.x() - offset.x(); + int y = position.y() - offset.y(); + int z = position.z() - offset.z(); return getParent().getBiomeType(x, y, z); } @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { - int x = position.getBlockX() - offset.getX(); - int y = position.getBlockY() - offset.getY(); - int z = position.getBlockZ() - offset.getZ(); + int x = position.x() - offset.x(); + int y = position.y() - offset.y(); + int z = position.z() - offset.z(); return getParent().setBiome(x, y, z, biome); } @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); return getParent().setBiome(x, y, z, biome); } @@ -262,9 +264,9 @@ public class BlockArrayClipboard implements Clipboard { ClipboardEntity ce = (ClipboardEntity) e; Location oldloc = ce.getLocation(); Location loc = new Location(oldloc.getExtent(), - oldloc.getX() + offset.getBlockX(), - oldloc.getY() + offset.getBlockY(), - oldloc.getZ() + offset.getBlockZ(), + oldloc.x() + offset.x(), + oldloc.y() + offset.y(), + oldloc.z() + offset.z(), oldloc.getYaw(), oldloc.getPitch() ); return new ClipboardEntity(loc, ce.entity); @@ -281,9 +283,9 @@ public class BlockArrayClipboard implements Clipboard { ClipboardEntity ce = (ClipboardEntity) e; Location oldloc = ce.getLocation(); Location loc = new Location(oldloc.getExtent(), - oldloc.getX() + offset.getBlockX(), - oldloc.getY() + offset.getBlockY(), - oldloc.getZ() + offset.getBlockZ(), + oldloc.x() + offset.x(), + oldloc.y() + offset.y(), + oldloc.z() + offset.z(), oldloc.getYaw(), oldloc.getPitch() ); return new ClipboardEntity(loc, ce.entity); @@ -296,9 +298,9 @@ public class BlockArrayClipboard implements Clipboard { @Nullable public Entity createEntity(Location location, BaseEntity entity) { Location l = new Location(location.getExtent(), - location.getX() - offset.getBlockX(), - location.getY() - offset.getBlockY(), - location.getZ() - offset.getBlockZ(), + location.x() - offset.x(), + location.y() - offset.y(), + location.z() - offset.z(), location.getYaw(), location.getPitch() ); return getParent().createEntity(l, entity); @@ -308,9 +310,9 @@ public class BlockArrayClipboard implements Clipboard { @Nullable public Entity createEntity(Location location, BaseEntity entity, UUID uuid) { Location l = new Location(location.getExtent(), - location.getX() - offset.getBlockX(), - location.getY() - offset.getBlockY(), - location.getZ() - offset.getBlockZ(), + location.x() - offset.x(), + location.y() - offset.y(), + location.z() - offset.z(), location.getYaw(), location.getPitch() ); return getParent().createEntity(l, entity, uuid); @@ -318,33 +320,33 @@ public class BlockArrayClipboard implements Clipboard { @Override public void removeEntity(int x, int y, int z, UUID uuid) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); getParent().removeEntity(x, y, z, uuid); } @Override public BlockState getBlock(int x, int y, int z) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); return getParent().getBlock(x, y, z); } @Override public BaseBlock getFullBlock(int x, int y, int z) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); return getParent().getFullBlock(x, y, z); } @Override public BiomeType getBiomeType(int x, int y, int z) { - x -= offset.getX(); - y -= offset.getY(); - z -= offset.getZ(); + x -= offset.x(); + y -= offset.y(); + z -= offset.z(); return getParent().getBiomeType(x, y, z); } @@ -359,7 +361,7 @@ public class BlockArrayClipboard implements Clipboard { public Iterator iterator2d() { MutableBlockVector2 mutable = new MutableBlockVector2(); return Iterators.transform(getParent().iterator2d(), input -> - mutable.setComponents(input.getX() + offset.getX(), input.getZ() + offset.getZ())); + mutable.setComponents(input.x() + offset.x(), input.z() + offset.z())); } @Override @@ -409,7 +411,7 @@ public class BlockArrayClipboard implements Clipboard { private final float pitch; public ClipboardEntity(Location loc, BaseEntity entity) { - this((Clipboard) loc.getExtent(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), entity); + this((Clipboard) loc.getExtent(), loc.x(), loc.y(), loc.z(), loc.getYaw(), loc.getPitch(), entity); } public ClipboardEntity(Clipboard clipboard, double x, double y, double z, float yaw, float pitch, BaseEntity entity) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java index 15d6365e7..cac9f4a7b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java @@ -31,6 +31,7 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSessionBuilder; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; @@ -40,6 +41,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.internal.util.ClipboardTransformBaker; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.Region; @@ -73,7 +75,10 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl /** * Creates a new {@link ReadOnlyClipboard}. + * + * @deprecated Internal use only. Use {@link BlockArrayClipboard#BlockArrayClipboard(Region)} */ + @Deprecated static Clipboard create(Region region) { checkNotNull(region); checkNotNull( @@ -95,7 +100,10 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl * - {@link DiskOptimizedClipboard} * - {@link CPUOptimizedClipboard} * - {@link MemoryOptimizedClipboard} + * + * @deprecated Internal use only. Use {@link BlockArrayClipboard#BlockArrayClipboard(Region, UUID)} */ + @Deprecated static Clipboard create(Region region, UUID uuid) { if (Settings.settings().CLIPBOARD.USE_DISK) { return new DiskOptimizedClipboard(region, uuid); @@ -138,10 +146,9 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl void setOrigin(BlockVector3 origin); /** - * Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)} + * Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector3)} * strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null} - * if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting - * to ocean, instead of having biomes explicitly set. + * if biomes aren't present. * * @return true if the clipboard has biome data set */ @@ -149,6 +156,21 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl return false; } + /** + * Returns a clipboard with a given transform baked in. + * + *

+ * Note: This method may return the same clipboard object, if a copy is needed then you should check the returned value for identity equality and copy if needed. + *

+ * + * @param transform The transform + * @return The new clipboard + * @throws WorldEditException if the copy encounters an error + */ + default Clipboard transform(Transform transform) throws WorldEditException { + return ClipboardTransformBaker.bakeTransform(this, transform); + } + //FAWE start /** @@ -157,15 +179,15 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl void removeEntity(Entity entity); default int getWidth() { - return getDimensions().getBlockX(); + return getDimensions().x(); } default int getHeight() { - return getDimensions().getBlockY(); + return getDimensions().y(); } default int getLength() { - return getDimensions().getBlockZ(); + return getDimensions().z(); } default int getArea() { @@ -374,17 +396,17 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl final BlockVector3 origin = this.getOrigin(); // To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin) - final int relx = to.getBlockX() - origin.getBlockX(); - final int rely = to.getBlockY() - origin.getBlockY(); - final int relz = to.getBlockZ() - origin.getBlockZ(); + final int relx = to.x() - origin.x(); + final int rely = to.y() - origin.y(); + final int relz = to.z() - origin.z(); pasteBiomes &= Clipboard.this.hasBiomes(); for (BlockVector3 pos : this) { BaseBlock block = pos.getFullBlock(this); - int xx = pos.getX() + relx; - int yy = pos.getY() + rely; - int zz = pos.getZ() + relz; + int xx = pos.x() + relx; + int yy = pos.y() + rely; + int zz = pos.z() + relz; if (pasteBiomes) { extent.setBiome(xx, yy, zz, pos.getBiome(this)); } @@ -394,20 +416,20 @@ public interface Clipboard extends Extent, Iterable, Closeable, Fl extent.setBlock(xx, yy, zz, block); } // Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin) - final int entityOffsetX = to.getBlockX() - origin.getBlockX(); - final int entityOffsetY = to.getBlockY() - origin.getBlockY(); - final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ(); + final int entityOffsetX = to.x() - origin.x(); + final int entityOffsetY = to.y() - origin.y(); + final int entityOffsetZ = to.z() - origin.z(); // entities if (pasteEntities) { for (Entity entity : this.getEntities()) { // skip players on pasting schematic - if (entity.getState() != null && entity.getState().getType().getId() + if (entity.getState() != null && entity.getState().getType().id() .equals("minecraft:player")) { continue; } Location pos = entity.getLocation(); - Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX, - pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(), + Location newPos = new Location(pos.getExtent(), pos.x() + entityOffsetX, + pos.y() + entityOffsetY, pos.z() + entityOffsetZ, pos.getYaw(), pos.getPitch() ); extent.createEntity(newPos, entity.getState()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/BuiltInClipboardFormat.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/BuiltInClipboardFormat.java index 5aafa220e..a26e7c99a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/BuiltInClipboardFormat.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/BuiltInClipboardFormat.java @@ -19,28 +19,39 @@ package com.sk89q.worldedit.extent.clipboard.io; -import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReader; -import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriterV2; +import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriterV3; import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure; import com.fastasyncworldedit.core.extent.clipboard.io.schematic.PNGWriter; import com.fastasyncworldedit.core.internal.io.ResettableFileInputStream; import com.google.common.collect.ImmutableSet; -import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NamedTag; -import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV1Reader; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV2Reader; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV2Writer; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader; +import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Writer; +import it.unimi.dsi.fastutil.io.FastBufferedInputStream; import org.anarres.parallelgzip.ParallelGZIPOutputStream; +import org.enginehub.linbus.stream.LinBinaryIO; +import org.enginehub.linbus.tree.LinRootEntry; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Collections; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -48,23 +59,14 @@ import java.util.zip.GZIPOutputStream; /** * A collection of supported clipboard formats. */ +@SuppressWarnings("removal") //FAWE: suppress JNBT deprecations public enum BuiltInClipboardFormat implements ClipboardFormat { //FAWE start - register fast clipboard io - FAST("fast", "fawe", "sponge", "schem") { - @Override - public String getPrimaryFileExtension() { - return "schem"; - } - + FAST_V3("fast", "fawe", "schem") { @Override public ClipboardReader getReader(InputStream inputStream) throws IOException { - if (inputStream instanceof FileInputStream) { - inputStream = new ResettableFileInputStream((FileInputStream) inputStream); - } - BufferedInputStream buffered = new BufferedInputStream(inputStream); - NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered))); - return new FastSchematicReader(nbtStream); + return new FastSchematicReaderV3(inputStream); } @Override @@ -77,15 +79,106 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { gzip = new ParallelGZIPOutputStream(outputStream); } NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip)); - return new FastSchematicWriter(nbtStream); + return new FastSchematicWriterV3(nbtStream); + } + + @Override + public boolean isFormat(final InputStream inputStream) { + try (final DataInputStream stream = new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(inputStream))); + final NBTInputStream nbt = new NBTInputStream(stream)) { + if (stream.readByte() != NBTConstants.TYPE_COMPOUND) { + return false; + } + stream.skipNBytes(2); // TAG name length ("" = 0), no need to read name as no bytes are written for root tag + if (stream.readByte() != NBTConstants.TYPE_COMPOUND) { + return false; + } + stream.skipNBytes(2); // TAG name length ("Schematic" = 9) + stream.skipNBytes(9); // "Schematic" + + // We can't guarantee the specific order of nbt data, so scan and skip, if required + do { + byte type = stream.readByte(); + String name = stream.readUTF(); + if (type == NBTConstants.TYPE_END) { + return false; + } + if (type == NBTConstants.TYPE_INT && name.equals("Version")) { + return stream.readInt() == FastSchematicWriterV3.CURRENT_VERSION; + } + nbt.readTagPayloadLazy(type, 0); + } while (true); + } catch (IOException ignored) { + } + return false; } @Override public boolean isFormat(File file) { String name = file.getName().toLowerCase(Locale.ROOT); - return name.endsWith(".schem") || name.endsWith(".sponge"); + if (name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce")) { + return false; + } + return super.isFormat(file); } + @Override + public String getPrimaryFileExtension() { + return "schem"; + } + + @Override + public Set getExplicitFileExtensions() { + return Set.of("schem3", "sponge3", "fast3"); + } + }, + FAST_V2("fast.2", "fawe.2", "schem.2") { + @Override + public String getPrimaryFileExtension() { + return "schem"; + } + + @Override + public ClipboardReader getReader(InputStream inputStream) throws IOException { + if (inputStream instanceof FileInputStream) { + inputStream = new ResettableFileInputStream((FileInputStream) inputStream); + } + BufferedInputStream buffered = new BufferedInputStream(inputStream); + NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered))); + return new FastSchematicReaderV2(nbtStream); + } + + @Override + public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { + OutputStream gzip; + if (outputStream instanceof ParallelGZIPOutputStream || outputStream instanceof GZIPOutputStream) { + gzip = outputStream; + } else { + outputStream = new BufferedOutputStream(outputStream); + gzip = new ParallelGZIPOutputStream(outputStream); + } + NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip)); + return new FastSchematicWriterV2(nbtStream); + } + + @Override + public boolean isFormat(InputStream inputStream) { + return detectOldSpongeSchematic(inputStream, FastSchematicWriterV2.CURRENT_VERSION); + } + + @Override + public boolean isFormat(File file) { + String name = file.getName().toLowerCase(Locale.ROOT); + if (name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce")) { + return false; + } + return super.isFormat(file); + } + + @Override + public Set getExplicitFileExtensions() { + return Set.of("schem2", "sponge2", "fast2"); + } }, //FAWE end @@ -115,7 +208,61 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { @Override public boolean isFormat(File file) { String name = file.getName().toLowerCase(Locale.ROOT); - return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce"); + if (!name.endsWith(".schematic") && !name.endsWith(".mcedit") && !name.endsWith(".mce")) { + return false; + } + return super.isFormat(file); + } + + @Override + public boolean isFormat(InputStream inputStream) { + LinRootEntry rootEntry; + try { + DataInputStream stream = new DataInputStream(new GZIPInputStream(inputStream)); + rootEntry = LinBinaryIO.readUsing(stream, LinRootEntry::readFrom); + } catch (Exception e) { + return false; + } + if (!rootEntry.name().equals("Schematic")) { + return false; + } + return rootEntry.value().value().containsKey("Materials"); + } + + @Override + public Set getExplicitFileExtensions() { + return Set.of("mcedit", "schem1", "sponge1", "fast1"); + } + }, + SPONGE_V1_SCHEMATIC("sponge.1") { + @Override + public String getPrimaryFileExtension() { + return "schem"; + } + + @Override + public ClipboardReader getReader(InputStream inputStream) throws IOException { + return new SpongeSchematicV1Reader(LinBinaryIO.read(new DataInputStream(new GZIPInputStream(inputStream)))); + } + + @Override + public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { + throw new IOException("This format does not support saving"); + } + + @Override + public boolean isFormat(InputStream inputStream) { + return detectOldSpongeSchematic(inputStream, 1); + } + + @Override + public boolean isFormat(File file) { + return MCEDIT_SCHEMATIC.isFormat(file); + } + + @Override + public Set getExplicitFileExtensions() { + return Collections.emptySet(); } }, @@ -125,7 +272,8 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { * Avoid using with any large schematics/clipboards for reading/writing. */ @Deprecated - SPONGE_SCHEMATIC("slow", "safe") { + SPONGE_V2_SCHEMATIC("slow.2", "safe.2", "sponge.2") { // FAWE - edit aliases for fast + @Override public String getPrimaryFileExtension() { return "schem"; @@ -133,38 +281,58 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { @Override public ClipboardReader getReader(InputStream inputStream) throws IOException { - NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream)); - return new SpongeSchematicReader(nbtStream); + return new SpongeSchematicV2Reader(LinBinaryIO.read(new DataInputStream(new GZIPInputStream(inputStream)))); } @Override public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { - NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(outputStream)); - return new SpongeSchematicWriter(nbtStream); + return new SpongeSchematicV2Writer(new DataOutputStream(new GZIPOutputStream(outputStream))); + } + + @Override + public boolean isFormat(InputStream inputStream) { + return detectOldSpongeSchematic(inputStream, 2); } @Override public boolean isFormat(File file) { - try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) { - NamedTag rootTag = str.readNamedTag(); - if (!rootTag.getName().equals("Schematic")) { - return false; - } - CompoundTag schematicTag = (CompoundTag) rootTag.getTag(); + return FAST_V2.isFormat(file); + } - // Check - Map schematic = schematicTag.getValue(); - if (!schematic.containsKey("Version")) { - return false; - } - } catch (Exception e) { - return false; - } - - return true; + @Override + public Set getExplicitFileExtensions() { + return Collections.emptySet(); } }, + SPONGE_V3_SCHEMATIC("sponge.3", "slow", "safe") { // FAWE - edit aliases for fast + @Override + public String getPrimaryFileExtension() { + return "schem"; + } + + @Override + public ClipboardReader getReader(InputStream inputStream) throws IOException { + return new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(new GZIPInputStream(inputStream)))); + } + + @Override + public ClipboardWriter getWriter(OutputStream outputStream) throws IOException { + return new SpongeSchematicV3Writer(new DataOutputStream(new GZIPOutputStream(outputStream))); + } + + @Override + public boolean isFormat(File file) { + //FAWE start - delegate to stream-based isFormat approach of fast impl + return FAST_V3.isFormat(file); + //FAWE end + } + + @Override + public Set getExplicitFileExtensions() { + return Collections.emptySet(); + } + }, //FAWE start - recover schematics with bad entity data & register other clipboard formats BROKENENTITY("brokenentity", "legacyentity", "le", "be", "brokenentities", "legacyentities") { @Override @@ -179,7 +347,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { } BufferedInputStream buffered = new BufferedInputStream(inputStream); NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered))); - FastSchematicReader reader = new FastSchematicReader(nbtStream); + FastSchematicReaderV2 reader = new FastSchematicReaderV2(nbtStream); reader.setBrokenEntities(true); return reader; } @@ -194,7 +362,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { gzip = new ParallelGZIPOutputStream(outputStream); } NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip)); - FastSchematicWriter writer = new FastSchematicWriter(nbtStream); + FastSchematicWriterV2 writer = new FastSchematicWriterV2(nbtStream); writer.setBrokenEntities(true); return writer; } @@ -204,6 +372,10 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { return false; } + @Override + public Set getExplicitFileExtensions() { + return Collections.emptySet(); + } }, /** @@ -232,9 +404,42 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { } @Override - public boolean isFormat(File file) { - String name = file.getName().toLowerCase(Locale.ROOT); - return name.endsWith(".nbt"); + public boolean isFormat(InputStream inputStream) { + try (final DataInputStream stream = new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(inputStream))); + final NBTInputStream nbt = new NBTInputStream(stream)) { + if (stream.readByte() != NBTConstants.TYPE_COMPOUND) { + return false; + } + NamedTag namedTag = nbt.readNamedTag(); + if (!namedTag.getName().isEmpty()) { + return false; + } + + // We can't guarantee the specific order of nbt data, so scan and skip, if required + do { + byte type = stream.readByte(); + String name = stream.readUTF(); + if (type == NBTConstants.TYPE_END) { + return false; + } + if (type == NBTConstants.TYPE_LIST && name.equals("size")) { + return true; + } + nbt.readTagPayloadLazy(type, 0); + } while (true); + } catch (IOException ignored) { + } + return false; + } + + @Override + public boolean isFormat(final File file) { + return file.getName().toLowerCase(Locale.ROOT).endsWith(".nbt") && super.isFormat(file); + } + + @Override + public Set getExplicitFileExtensions() { + return Set.of("nbt"); } }, @@ -262,9 +467,61 @@ public enum BuiltInClipboardFormat implements ClipboardFormat { public String getPrimaryFileExtension() { return "png"; } + + @Override + public Set getExplicitFileExtensions() { + return Set.of("png"); + } }; //FAWE end + private static boolean detectOldSpongeSchematic(InputStream inputStream, int version) { + //FAWE start - dont utilize linbus - WorldEdit approach is not really streamed + try (final DataInputStream stream = new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(inputStream))); + final NBTInputStream nbt = new NBTInputStream(stream)) { + if (stream.readByte() != NBTConstants.TYPE_COMPOUND) { + return false; + } + stream.skipNBytes(2); // TAG name length ("Schematic" = 9) + stream.skipNBytes(9); // "Schematic" + + // We can't guarantee the specific order of nbt data, so scan and skip, if required + do { + byte type = stream.readByte(); + String name = stream.readUTF(); + if (type == NBTConstants.TYPE_END) { + return false; + } + if (type == NBTConstants.TYPE_INT && name.equals("Version")) { + return stream.readInt() == version; + } + nbt.readTagPayloadLazy(type, 0); + } while (true); + } catch (IOException ignored) { + } + return false; + } + + /** + * For backwards compatibility, this points to the Sponge Schematic Specification (Version 2) + * format. This should not be used going forwards. + * + * @deprecated Use {@link #SPONGE_V2_SCHEMATIC} or {@link #SPONGE_V3_SCHEMATIC} + */ + @Deprecated + public static final BuiltInClipboardFormat SPONGE_SCHEMATIC = SPONGE_V2_SCHEMATIC; + + //FAWE start + /** + * For backwards compatibility, this points to the fast implementation of the Sponge Schematic Specification (Version 2) + * format. This should not be used going forwards. + * + * @deprecated Use {@link #FAST_V2} or {@link #FAST_V3} + */ + @Deprecated + public static final BuiltInClipboardFormat FAST = FAST_V2; + //FAWE end + private final ImmutableSet aliases; BuiltInClipboardFormat(String... aliases) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java index cb5cd1b7a..1961dd8cb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java @@ -35,6 +35,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URL; +import java.nio.file.Files; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; @@ -82,7 +83,29 @@ public interface ClipboardFormat { * @param file the file * @return true if the given file is of this format */ - boolean isFormat(File file); + default boolean isFormat(File file) { + try (InputStream stream = Files.newInputStream(file.toPath())) { + return isFormat(stream); + } catch (IOException e) { + return false; + } + } + + /** + * Return whether the given stream is of this format. + * + * @apiNote The caller is responsible for the following: + *
    + *
  • Closing the input stream
  • + *
+ * + * @param inputStream The stream + * @return true if the given stream is of this format + * @since 2.11.1 + */ + default boolean isFormat(InputStream inputStream) { + return false; + } /** * Get the file extension this format primarily uses. @@ -101,6 +124,13 @@ public interface ClipboardFormat { //FAWE start + /** + * Get the explicit file extensions (e.g. .schem2) this format is commonly known to use. + * + * @return The explicit file extensions this format might be known by + */ + Set getExplicitFileExtensions(); + /** * Sets the actor's clipboard. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java index b00c9ea5b..d1529c803 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java @@ -26,7 +26,6 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder; import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.util.MainUtil; -import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.io.ByteSource; @@ -51,6 +50,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -64,14 +64,17 @@ import static com.google.common.base.Preconditions.checkNotNull; public class ClipboardFormats { private static final Map aliasMap = new HashMap<>(); - private static final Multimap fileExtensionMap = HashMultimap.create(); + // FAWE start - keep order of ClipboardFormat entries -> prefer FAST over SPONGE_SCHEMATIC + private static final Multimap fileExtensionMap = Multimaps.newMultimap(new HashMap<>(), LinkedHashSet::new); + private static final Multimap explicitFileExtensionMap = Multimaps.newMultimap(new HashMap<>(), LinkedHashSet::new); + // FAWE end private static final List registeredFormats = new ArrayList<>(); public static void registerClipboardFormat(ClipboardFormat format) { checkNotNull(format); for (String key : format.getAliases()) { - String lowKey = key.toLowerCase(Locale.ENGLISH); + String lowKey = key.toLowerCase(Locale.ROOT); ClipboardFormat old = aliasMap.put(lowKey, format); if (old != null) { aliasMap.put(lowKey, old); @@ -81,9 +84,13 @@ public class ClipboardFormats { } } for (String ext : format.getFileExtensions()) { - String lowExt = ext.toLowerCase(Locale.ENGLISH); + String lowExt = ext.toLowerCase(Locale.ROOT); fileExtensionMap.put(lowExt, format); } + for (String ext : format.getExplicitFileExtensions()) { + String lowExt = ext.toLowerCase(Locale.ROOT); + explicitFileExtensionMap.put(lowExt, format); + } registeredFormats.add(format); } @@ -102,7 +109,7 @@ public class ClipboardFormats { @Nullable public static ClipboardFormat findByAlias(String alias) { checkNotNull(alias); - return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim()); + return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim()); } /** @@ -145,6 +152,18 @@ public class ClipboardFormats { return fileExtensionMap.keySet().toArray(new String[fileExtensionMap.keySet().size()]); } + //FAWE start + + /** + * A mapping from explicit extensions (e.g. .schem2) to formats. + * + * @return a multimap from a file extension to the potential matching formats. + */ + public static Multimap getExplicitFileExtensionMap() { + return Multimaps.unmodifiableMultimap(explicitFileExtensionMap); + } + //FAWE end + private ClipboardFormats() { } @@ -155,8 +174,10 @@ public class ClipboardFormats { * * @param extension the extension * @return the format, otherwise null if one cannot be detected + * @deprecated DO NOT USE. Sponge formats 2 and 3 both use .schem by default. */ @Nullable + @Deprecated(forRemoval = true, since = "2.11.1") public static ClipboardFormat findByExtension(String extension) { checkNotNull(extension); @@ -170,6 +191,25 @@ public class ClipboardFormats { } + /** + * Detect the format given an explicit extension, e.g. ".schem2" + * + * @param extension the extension + * @return the format, otherwise null if one cannot be detected + */ + @Nullable + public static ClipboardFormat findByExplicitExtension(String extension) { + checkNotNull(extension); + + Collection> entries = getExplicitFileExtensionMap().entries(); + for (Map.Entry entry : entries) { + if (entry.getKey().equalsIgnoreCase(extension)) { + return entry.getValue(); + } + } + return null; + } + public static MultiClipboardHolder loadAllFromInput( Actor player, String input, @@ -229,7 +269,7 @@ public class ClipboardFormats { } if (format == null && input.matches(".*\\.[\\w].*")) { String extension = input.substring(input.lastIndexOf('.') + 1); - format = findByExtension(extension); + format = findByExplicitExtension(extension); } f = MainUtil.resolve(dir, input, format, true); } @@ -300,7 +340,7 @@ public class ClipboardFormats { byte[] buffer = new byte[8192]; while ((entry = zip.getNextEntry()) != null) { String filename = entry.getName(); - ClipboardFormat format = findByExtension(filename); + ClipboardFormat format = findByExtension(filename); // FIXME if (format != null) { FastByteArrayOutputStream out = new FastByteArrayOutputStream(); int len; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardWriter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardWriter.java index b7cf7a050..d3420f658 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardWriter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardWriter.java @@ -50,9 +50,9 @@ public interface ClipboardWriter extends Closeable { //FAWE start default Tag writeVector(Vector3 vector) { List list = new ArrayList<>(); - list.add(new DoubleTag(vector.getX())); - list.add(new DoubleTag(vector.getY())); - list.add(new DoubleTag(vector.getZ())); + list.add(new DoubleTag(vector.x())); + list.add(new DoubleTag(vector.y())); + list.add(new DoubleTag(vector.z())); return new ListTag(DoubleTag.class, list); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java index aebef3e9a..8e54249cd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java @@ -20,17 +20,7 @@ package com.sk89q.worldedit.extent.clipboard.io; import com.google.common.collect.ImmutableList; -import com.sk89q.jnbt.AdventureNBTConverter; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.NamedTag; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -49,7 +39,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.collection.BlockMap; -import com.sk89q.worldedit.world.DataFixer; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.entity.EntityType; @@ -57,27 +47,26 @@ import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; import com.sk89q.worldedit.world.storage.NBTConversions; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; +import java.io.UncheckedIOException; import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.Optional; +import java.util.NoSuchElementException; import java.util.Set; -import static com.google.common.base.Preconditions.checkNotNull; - /** * Reads schematic files that are compatible with MCEdit and other editors. */ public class MCEditSchematicReader extends NBTSchematicReader { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final NBTInputStream inputStream; - private final DataFixer fixer; + private final LinRootEntry root; private static final ImmutableList COMPATIBILITY_HANDLERS = ImmutableList.of( new SignCompatibilityHandler(), @@ -98,30 +87,30 @@ public class MCEditSchematicReader extends NBTSchematicReader { * @param inputStream the input stream to read from */ public MCEditSchematicReader(NBTInputStream inputStream) { - checkNotNull(inputStream); - this.inputStream = inputStream; - this.fixer = null; - //com.sk89q.worldedit.WorldEdit.getInstance().getPlatformManager().queryCapability( - //com.sk89q.worldedit.extension.platform.Capability.WORLD_EDITING).getDataFixer(); + try { + var tag = inputStream.readNamedTag(); + this.root = new LinRootEntry(tag.getName(), (LinCompoundTag) tag.getTag().toLinTag()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + MCEditSchematicReader(LinRootEntry root) { + this.root = root; } @Override public Clipboard read() throws IOException { // Schematic tag - NamedTag rootTag = inputStream.readNamedTag(); - if (!rootTag.getName().equals("Schematic")) { + if (!root.name().equals("Schematic")) { throw new IOException("Tag 'Schematic' does not exist or is not first"); } - CompoundTag schematicTag = (CompoundTag) rootTag.getTag(); + var schematicTag = root.value(); - // Check - Map schematic = schematicTag.getValue(); - if (!schematic.containsKey("Blocks")) { + if (!schematicTag.value().containsKey("Blocks")) { throw new IOException("Schematic file is missing a 'Blocks' tag"); } - - // Check type of Schematic - String materials = requireTag(schematic, "Materials", StringTag.class).getValue(); + String materials = schematicTag.getTag("Materials", LinTagType.stringTag()).value(); if (!materials.equals("Alpha")) { throw new IOException("Schematic file is not an Alpha schematic"); } @@ -134,42 +123,45 @@ public class MCEditSchematicReader extends NBTSchematicReader { Region region; // Get information - short width = requireTag(schematic, "Width", ShortTag.class).getValue(); - short height = requireTag(schematic, "Height", ShortTag.class).getValue(); - short length = requireTag(schematic, "Length", ShortTag.class).getValue(); + short width = schematicTag.getTag("Width", LinTagType.shortTag()).valueAsShort(); + short height = schematicTag.getTag("Height", LinTagType.shortTag()).valueAsShort(); + short length = schematicTag.getTag("Length", LinTagType.shortTag()).valueAsShort(); try { - int originX = requireTag(schematic, "WEOriginX", IntTag.class).getValue(); - int originY = requireTag(schematic, "WEOriginY", IntTag.class).getValue(); - int originZ = requireTag(schematic, "WEOriginZ", IntTag.class).getValue(); + int originX = schematicTag.getTag("WEOriginX", LinTagType.intTag()).valueAsInt(); + int originY = schematicTag.getTag("WEOriginY", LinTagType.intTag()).valueAsInt(); + int originZ = schematicTag.getTag("WEOriginZ", LinTagType.intTag()).valueAsInt(); BlockVector3 min = BlockVector3.at(originX, originY, originZ); - int offsetX = requireTag(schematic, "WEOffsetX", IntTag.class).getValue(); - int offsetY = requireTag(schematic, "WEOffsetY", IntTag.class).getValue(); - int offsetZ = requireTag(schematic, "WEOffsetZ", IntTag.class).getValue(); + int offsetX = schematicTag.getTag("WEOffsetX", LinTagType.intTag()).valueAsInt(); + int offsetY = schematicTag.getTag("WEOffsetY", LinTagType.intTag()).valueAsInt(); + int offsetZ = schematicTag.getTag("WEOffsetZ", LinTagType.intTag()).valueAsInt(); BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ); origin = min.subtract(offset); region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE)); - } catch (IOException ignored) { + } catch (NoSuchElementException e) { origin = BlockVector3.ZERO; region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE)); } + + // ==================================================================== // Blocks // ==================================================================== // Get blocks - byte[] blockId = requireTag(schematic, "Blocks", ByteArrayTag.class).getValue(); - byte[] blockData = requireTag(schematic, "Data", ByteArrayTag.class).getValue(); + byte[] blockId = schematicTag.getTag("Blocks", LinTagType.byteArrayTag()).value(); + byte[] blockData = schematicTag.getTag("Data", LinTagType.byteArrayTag()).value(); byte[] addId = new byte[0]; short[] blocks = new short[blockId.length]; // Have to later combine IDs // We support 4096 block IDs using the same method as vanilla Minecraft, where // the highest 4 bits are stored in a separate byte array. - if (schematic.containsKey("AddBlocks")) { - addId = requireTag(schematic, "AddBlocks", ByteArrayTag.class).getValue(); + LinByteArrayTag addBlocks = schematicTag.findTag("AddBlocks", LinTagType.byteArrayTag()); + if (addBlocks != null) { + addId = addBlocks.value(); } // Combine the AddBlocks data with the first 8-bit block ID @@ -186,21 +178,17 @@ public class MCEditSchematicReader extends NBTSchematicReader { } // Need to pull out tile entities - final ListTag tileEntityTag = getTag(schematic, "TileEntities", ListTag.class); - List tileEntities = tileEntityTag == null ? new ArrayList<>() : tileEntityTag.getValue(); + var tileEntityTag = schematicTag.findListTag("TileEntities", LinTagType.compoundTag()); + List tileEntities = tileEntityTag == null ? List.of() : tileEntityTag.value(); BlockMap tileEntityBlocks = BlockMap.createForBaseBlock(); - for (Tag tag : tileEntities) { - if (!(tag instanceof CompoundTag)) { - continue; - } - CompoundTag t = (CompoundTag) tag; - Map values = new HashMap<>(t.getValue()); - String id = t.getString("id"); - values.put("id", new StringTag(convertBlockEntityId(id))); - int x = t.getInt("x"); - int y = t.getInt("y"); - int z = t.getInt("z"); + for (LinCompoundTag tag : tileEntities) { + var newTag = tag.toBuilder(); + String id = tag.getTag("id", LinTagType.stringTag()).value(); + newTag.putString("id", convertBlockEntityId(id)); + int x = tag.getTag("x", LinTagType.intTag()).valueAsInt(); + int y = tag.getTag("y", LinTagType.intTag()).valueAsInt(); + int z = tag.getTag("z", LinTagType.intTag()).valueAsInt(); int index = y * width * length + z * width + x; //FAWE start - tile entity safety - perhaps caused by the old issue with tile entities created in the wrong @@ -211,44 +199,17 @@ public class MCEditSchematicReader extends NBTSchematicReader { } BlockState block = getBlockState(blocks[index], blockData[index]); - BlockState newBlock = block; - if (newBlock != null) { - for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) { - if (handler.isAffectedBlock(newBlock)) { - newBlock = handler.updateNBT(block, values).toImmutableState(); - if (newBlock == null || values.isEmpty()) { - break; - } - } + if (block == null) { + continue; + } + var updatedBlock = block.toBaseBlock(LazyReference.from(newTag::build)); + for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) { + updatedBlock = handler.updateNbt(updatedBlock); + if (updatedBlock.getNbtReference() == null) { + break; } } - if (values.isEmpty()) { - t = null; - } else { - t = new CompoundTag(values); - } - - if (fixer != null && t != null) { - //FAWE start - BinaryTag - t = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( - DataFixer.FixTypes.BLOCK_ENTITY, - t.asBinaryTag(), - -1 - )); - //FAWE end - } - - BlockVector3 vec = BlockVector3.at(x, y, z); - // Insert into the map if we have changed the block or have a tag - BlockState blockToInsert = newBlock != null - ? newBlock - : (t != null ? block : null); - if (blockToInsert != null) { - BaseBlock baseBlock = t != null - ? blockToInsert.toBaseBlock(new CompoundTag(t.getValue())) - : blockToInsert.toBaseBlock(); - tileEntityBlocks.put(vec, baseBlock); - } + tileEntityBlocks.put(BlockVector3.at(x, y, z), updatedBlock); } BlockArrayClipboard clipboard = new BlockArrayClipboard(region); @@ -261,16 +222,10 @@ public class MCEditSchematicReader extends NBTSchematicReader { for (int z = 0; z < length; ++z) { int index = y * width * length + z * width + x; BlockVector3 pt = BlockVector3.at(x, y, z); - BaseBlock state = Optional.ofNullable(tileEntityBlocks.get(pt)) - .orElseGet(() -> { - BlockState blockState = getBlockState(blocks[index], blockData[index]); - return blockState == null ? null : blockState.toBaseBlock(); - }); - - try { - if (state != null) { - clipboard.setBlock(region.getMinimumPoint().add(pt), state); - } else { + BaseBlock state = tileEntityBlocks.get(pt); + if (state == null) { + BlockState blockState = getBlockState(blocks[index], blockData[index]); + if (blockState == null) { short block = blocks[index]; byte data = blockData[index]; int combined = block << 8 | data; @@ -278,9 +233,12 @@ public class MCEditSchematicReader extends NBTSchematicReader { LOGGER.warn("Unknown block when loading schematic: {} {}. This is most likely a" + "bad schematic.", block, data); } + continue; } - } catch (WorldEditException ignored) { // BlockArrayClipboard won't throw this + state = blockState.toBaseBlock(); } + + clipboard.setBlock(region.getMinimumPoint().add(pt), state); } } } @@ -289,40 +247,25 @@ public class MCEditSchematicReader extends NBTSchematicReader { // Entities // ==================================================================== - ListTag entityList = getTag(schematic, "Entities", ListTag.class); + var entityList = schematicTag.findListTag("Entities", LinTagType.compoundTag()); if (entityList != null) { - List entityTags = entityList.getValue(); - for (Tag tag : entityTags) { - if (tag instanceof CompoundTag) { - CompoundTag compound = (CompoundTag) tag; - if (fixer != null) { - //FAWE start - BinaryTag - compound = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( - DataFixer.FixTypes.ENTITY, - compound.asBinaryTag(), - -1 - )); - //FAWE end - } - String id = convertEntityId(compound.getString("id")); - Location location = NBTConversions.toLocation( - clipboard, - compound.getListTag("Pos"), - compound.getListTag("Rotation") - ); - if (!id.isEmpty()) { - EntityType entityType = EntityTypes.get(id.toLowerCase(Locale.ROOT)); - if (entityType != null) { - for (EntityNBTCompatibilityHandler compatibilityHandler : ENTITY_COMPATIBILITY_HANDLERS) { - if (compatibilityHandler.isAffectedEntity(entityType, compound)) { - compound = compatibilityHandler.updateNBT(entityType, compound); - } - } - BaseEntity state = new BaseEntity(entityType, compound); - clipboard.createEntity(location, state); - } else { - LOGGER.warn("Unknown entity when pasting schematic: " + id.toLowerCase(Locale.ROOT)); + for (LinCompoundTag tag : entityList.value()) { + String id = convertEntityId(tag.getTag("id", LinTagType.stringTag()).value()); + Location location = NBTConversions.toLocation( + clipboard, + tag.getListTag("Pos", LinTagType.doubleTag()), + tag.getListTag("Rotation", LinTagType.floatTag()) + ); + if (!id.isEmpty()) { + EntityType entityType = EntityTypes.get(id.toLowerCase(Locale.ROOT)); + if (entityType != null) { + for (EntityNBTCompatibilityHandler compatibilityHandler : ENTITY_COMPATIBILITY_HANDLERS) { + tag = compatibilityHandler.updateNbt(entityType, tag); } + BaseEntity state = new BaseEntity(entityType, LazyReference.computed(tag)); + clipboard.createEntity(location, state); + } else { + LOGGER.warn("Unknown entity when pasting schematic: " + id.toLowerCase(Locale.ROOT)); } } } @@ -494,7 +437,6 @@ public class MCEditSchematicReader extends NBTSchematicReader { @Override public void close() throws IOException { - inputStream.close(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/NBTSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/NBTSchematicReader.java index 0328b1c76..017f07e9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/NBTSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/NBTSchematicReader.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.extent.clipboard.io; import com.sk89q.jnbt.Tag; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.io.IOException; @@ -27,16 +28,19 @@ import java.util.Map; /** * Base class for NBT schematic readers. + * + * @deprecated These utility methods are provided by {@link LinCompoundTag} now. */ +@Deprecated public abstract class NBTSchematicReader implements ClipboardReader { - protected static T requireTag(Map items, String key, Class expected) throws IOException { + protected static > T requireTag(Map> items, String key, Class expected) throws IOException { if (!items.containsKey(key)) { throw new IOException("Schematic file is missing a \"" + key + "\" tag of type " + expected.getName()); } - Tag tag = items.get(key); + Tag tag = items.get(key); if (!expected.isInstance(tag)) { throw new IOException(key + " tag is not of tag type " + expected.getName() + ", got " + tag.getClass().getName() + " instead"); @@ -46,12 +50,12 @@ public abstract class NBTSchematicReader implements ClipboardReader { } @Nullable - protected static T getTag(Map items, String key, Class expected) { + protected static > T getTag(Map> items, String key, Class expected) { if (!items.containsKey(key)) { return null; } - Tag test = items.get(key); + Tag test = items.get(key); if (!expected.isInstance(test)) { return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicLoadException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicLoadException.java new file mode 100644 index 000000000..f94216669 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicLoadException.java @@ -0,0 +1,43 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io; + +import com.sk89q.worldedit.util.formatting.text.Component; + +/** + * Raised when a known exception occurs during schematic load. + */ +public final class SchematicLoadException extends RuntimeException { + + private final Component message; + + public SchematicLoadException(Component message) { + this.message = message; + } + + /** + * Get the message of this exception as a rich text component. + * + * @return The rich message + */ + public Component getRichMessage() { + return this.message; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicNbtUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicNbtUtil.java new file mode 100644 index 000000000..7da0aa164 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicNbtUtil.java @@ -0,0 +1,61 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io; + +import com.sk89q.jnbt.Tag; + +import java.io.IOException; +import java.util.Map; +import javax.annotation.Nullable; + +// note, when clearing deprecations these methods don't need to remain -- they're introduced in 7.3.0 +public class SchematicNbtUtil { + public static T requireTag(Map items, String key, Class expected) throws IOException { + if (!items.containsKey(key)) { + throw new IOException("Schematic file is missing a \"" + key + "\" tag of type " + + expected.getName()); + } + + Tag tag = items.get(key); + if (!expected.isInstance(tag)) { + throw new IOException(key + " tag is not of tag type " + expected.getName() + ", got " + + tag.getClass().getName() + " instead"); + } + + return expected.cast(tag); + } + + @Nullable + public static T getTag(Map items, String key, Class expected) { + if (!items.containsKey(key)) { + return null; + } + + Tag test = items.get(key); + if (!expected.isInstance(test)) { + return null; + } + + return expected.cast(test); + } + + private SchematicNbtUtil() { + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java deleted file mode 100644 index 464ef3e4f..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.extent.clipboard.io; - -import com.google.common.collect.Maps; -import com.sk89q.jnbt.AdventureNBTConverter; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.NamedTag; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.ParserContext; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.Platform; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.world.DataFixer; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.entity.EntityTypes; -import com.sk89q.worldedit.world.storage.NBTConversions; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.OptionalInt; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Reads schematic files using the Sponge Schematic Specification. - * - * @deprecated Slow, resource intensive, but sometimes safer than using the recommended - * {@link com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReader}. - * Avoid reading large schematics with this reader. - */ -@Deprecated -public class SpongeSchematicReader extends NBTSchematicReader { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final NBTInputStream inputStream; - private DataFixer fixer = null; - private int schematicVersion = -1; - private int dataVersion = -1; - - /** - * Create a new instance. - * - * @param inputStream the input stream to read from - */ - public SpongeSchematicReader(NBTInputStream inputStream) { - checkNotNull(inputStream); - this.inputStream = inputStream; - } - - @Override - public Clipboard read() throws IOException { - CompoundTag schematicTag = getBaseTag(); - Map schematic = schematicTag.getValue(); - - final Platform platform = WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.WORLD_EDITING); - int liveDataVersion = platform.getDataVersion(); - - if (schematicVersion == 1) { - dataVersion = Constants.DATA_VERSION_MC_1_13_2; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1- - fixer = platform.getDataFixer(); - return readVersion1(schematicTag); - } else if (schematicVersion == 2) { - dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue(); - if (dataVersion < 0) { - LOGGER.warn( - "Schematic has an unknown data version ({}). Data may be incompatible.", - dataVersion - ); - // Do not DFU unknown data - dataVersion = liveDataVersion; - } - if (dataVersion > liveDataVersion) { - LOGGER.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.", - dataVersion, liveDataVersion - ); - } else if (dataVersion < liveDataVersion) { - fixer = platform.getDataFixer(); - if (fixer != null) { - LOGGER.info("Schematic was made in an older Minecraft version ({} < {}), will attempt DFU.", - dataVersion, liveDataVersion - ); - } else { - LOGGER.info( - "Schematic was made in an older Minecraft version ({} < {}), but DFU is not available. Data may be incompatible.", - dataVersion, - liveDataVersion - ); - } - } - - BlockArrayClipboard clip = readVersion1(schematicTag); - return readVersion2(clip, schematicTag); - } - throw new IOException("This schematic version is not supported; Version: " + schematicVersion + ", DataVersion: " + dataVersion + "." + - "It's very likely your schematic has an invalid file extension, if the schematic has been created on a version lower than" + - "1.13.2, the extension MUST be `.schematic`, elsewise the schematic can't be read properly."); - } - - @Override - public OptionalInt getDataVersion() { - try { - CompoundTag schematicTag = getBaseTag(); - Map schematic = schematicTag.getValue(); - if (schematicVersion == 1) { - return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2); - } else if (schematicVersion == 2) { - int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue(); - if (dataVersion < 0) { - return OptionalInt.empty(); - } - return OptionalInt.of(dataVersion); - } - return OptionalInt.empty(); - } catch (IOException e) { - return OptionalInt.empty(); - } - } - - private CompoundTag getBaseTag() throws IOException { - NamedTag rootTag = inputStream.readNamedTag(); - CompoundTag schematicTag = (CompoundTag) rootTag.getTag(); - - // Check - Map schematic = schematicTag.getValue(); - - schematicVersion = requireTag(schematic, "Version", IntTag.class).getValue(); - return schematicTag; - } - - private BlockArrayClipboard readVersion1(CompoundTag schematicTag) throws IOException { - BlockVector3 origin; - Region region; - Map schematic = schematicTag.getValue(); - - int width = requireTag(schematic, "Width", ShortTag.class).getValue(); - int height = requireTag(schematic, "Height", ShortTag.class).getValue(); - int length = requireTag(schematic, "Length", ShortTag.class).getValue(); - - IntArrayTag offsetTag = getTag(schematic, "Offset", IntArrayTag.class); - int[] offsetParts; - if (offsetTag != null) { - offsetParts = offsetTag.getValue(); - if (offsetParts.length != 3) { - throw new IOException("Invalid offset specified in schematic."); - } - } else { - offsetParts = new int[]{0, 0, 0}; - } - - BlockVector3 min = BlockVector3.at(offsetParts[0], offsetParts[1], offsetParts[2]); - - CompoundTag metadataTag = getTag(schematic, "Metadata", CompoundTag.class); - if (metadataTag != null && metadataTag.containsKey("WEOffsetX")) { - // We appear to have WorldEdit Metadata - Map metadata = metadataTag.getValue(); - int offsetX = requireTag(metadata, "WEOffsetX", IntTag.class).getValue(); - int offsetY = requireTag(metadata, "WEOffsetY", IntTag.class).getValue(); - int offsetZ = requireTag(metadata, "WEOffsetZ", IntTag.class).getValue(); - BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ); - origin = min.subtract(offset); - region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE)); - } else { - origin = min; - region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE)); - } - - IntTag paletteMaxTag = getTag(schematic, "PaletteMax", IntTag.class); - Map paletteObject = requireTag(schematic, "Palette", CompoundTag.class).getValue(); - if (paletteMaxTag != null && paletteObject.size() != paletteMaxTag.getValue()) { - throw new IOException("Block palette size does not match expected size."); - } - - Map palette = new HashMap<>(); - - ParserContext parserContext = new ParserContext(); - parserContext.setRestricted(false); - parserContext.setTryLegacy(false); - parserContext.setPreferringWildcard(false); - - for (String palettePart : paletteObject.keySet()) { - int id = requireTag(paletteObject, palettePart, IntTag.class).getValue(); - if (fixer != null) { - palettePart = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion); - } - BlockState state; - try { - state = WorldEdit.getInstance().getBlockFactory().parseFromInput(palettePart, parserContext).toImmutableState(); - } catch (InputParseException e) { - LOGGER.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air."); - state = BlockTypes.AIR.getDefaultState(); - } - palette.put(id, state); - } - - byte[] blocks = requireTag(schematic, "BlockData", ByteArrayTag.class).getValue(); - - Map> tileEntitiesMap = new HashMap<>(); - ListTag tileEntities = getTag(schematic, "BlockEntities", ListTag.class); - if (tileEntities == null) { - tileEntities = getTag(schematic, "TileEntities", ListTag.class); - } - if (tileEntities != null) { - List> tileEntityTags = tileEntities.getValue().stream() - .map(tag -> (CompoundTag) tag) - .map(CompoundTag::getValue) - .collect(Collectors.toList()); - - for (Map tileEntity : tileEntityTags) { - int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue(); - final BlockVector3 pt = BlockVector3.at(pos[0], pos[1], pos[2]); - Map values = Maps.newHashMap(tileEntity); - values.put("x", new IntTag(pt.getBlockX())); - values.put("y", new IntTag(pt.getBlockY())); - values.put("z", new IntTag(pt.getBlockZ())); - //FAWE start - support old, corrupt schematics - Tag id = values.get("Id"); - if (id == null) { - id = values.get("id"); - } - if (id == null) { - continue; - } - values.put("id", id); - //FAWE end - values.remove("Id"); - values.remove("Pos"); - if (fixer != null) { - //FAWE start - BinaryTag - tileEntity = ((CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( - DataFixer.FixTypes.BLOCK_ENTITY, - new CompoundTag(values).asBinaryTag(), - dataVersion - ))).getValue(); - //FAWE end - } else { - tileEntity = values; - } - tileEntitiesMap.put(pt, tileEntity); - } - } - - BlockArrayClipboard clipboard = new BlockArrayClipboard(region); - clipboard.setOrigin(origin); - - int index = 0; - int i = 0; - int value; - int varintLength; - while (i < blocks.length) { - value = 0; - varintLength = 0; - - while (true) { - value |= (blocks[i] & 127) << (varintLength++ * 7); - if (varintLength > 5) { - throw new IOException("VarInt too big (probably corrupted data)"); - } - if ((blocks[i] & 128) != 128) { - i++; - break; - } - i++; - } - // index = (y * length * width) + (z * width) + x - int y = index / (width * length); - int z = (index % (width * length)) / width; - int x = (index % (width * length)) % width; - BlockState state = palette.get(value); - BlockVector3 pt = BlockVector3.at(x, y, z); - try { - if (tileEntitiesMap.containsKey(pt)) { - clipboard.setBlock( - clipboard.getMinimumPoint().add(pt), - state.toBaseBlock(new CompoundTag(tileEntitiesMap.get(pt))) - ); - } else { - clipboard.setBlock(clipboard.getMinimumPoint().add(pt), state); - } - } catch (WorldEditException e) { - throw new IOException("Failed to load a block in the schematic"); - } - - index++; - } - - return clipboard; - } - - private Clipboard readVersion2(BlockArrayClipboard version1, CompoundTag schematicTag) throws IOException { - Map schematic = schematicTag.getValue(); - if (schematic.containsKey("BiomeData")) { - readBiomes(version1, schematic); - } - if (schematic.containsKey("Entities")) { - readEntities(version1, schematic); - } - return version1; - } - - private void readBiomes(BlockArrayClipboard clipboard, Map schematic) throws IOException { - ByteArrayTag dataTag = requireTag(schematic, "BiomeData", ByteArrayTag.class); - IntTag maxTag = requireTag(schematic, "BiomePaletteMax", IntTag.class); - CompoundTag paletteTag = requireTag(schematic, "BiomePalette", CompoundTag.class); - - Map palette = new HashMap<>(); - if (maxTag.getValue() != paletteTag.getValue().size()) { - throw new IOException("Biome palette size does not match expected size."); - } - - for (Entry palettePart : paletteTag.getValue().entrySet()) { - String key = palettePart.getKey(); - if (fixer != null) { - key = fixer.fixUp(DataFixer.FixTypes.BIOME, key, dataVersion); - } - BiomeType biome = BiomeTypes.get(key); - if (biome == null) { - LOGGER.warn("Unknown biome type :" + key - + " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?"); - } - Tag idTag = palettePart.getValue(); - if (!(idTag instanceof IntTag)) { - throw new IOException("Biome mapped to non-Int tag."); - } - palette.put(((IntTag) idTag).getValue(), biome); - } - - int width = clipboard.getDimensions().getX(); - - byte[] biomes = dataTag.getValue(); - int biomeIndex = 0; - int biomeJ = 0; - int bVal; - int varIntLength; - BlockVector3 min = clipboard.getMinimumPoint(); - while (biomeJ < biomes.length) { - bVal = 0; - varIntLength = 0; - - while (true) { - bVal |= (biomes[biomeJ] & 127) << (varIntLength++ * 7); - if (varIntLength > 5) { - throw new IOException("VarInt too big (probably corrupted data)"); - } - if (((biomes[biomeJ] & 128) != 128)) { - biomeJ++; - break; - } - biomeJ++; - } - int z = biomeIndex / width; - int x = biomeIndex % width; - BiomeType type = palette.get(bVal); - for (int y = 0; y < clipboard.getRegion().getHeight(); y++) { - clipboard.setBiome(min.add(x, y, z), type); - } - biomeIndex++; - } - } - - private void readEntities(BlockArrayClipboard clipboard, Map schematic) throws IOException { - List entList = requireTag(schematic, "Entities", ListTag.class).getValue(); - if (entList.isEmpty()) { - return; - } - for (Tag et : entList) { - if (!(et instanceof CompoundTag)) { - continue; - } - CompoundTag entityTag = (CompoundTag) et; - Map tags = entityTag.getValue(); - String id = requireTag(tags, "Id", StringTag.class).getValue(); - entityTag = entityTag.createBuilder().putString("id", id).remove("Id").build(); - - if (fixer != null) { - //FAWE start - BinaryTag - entityTag = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp( - DataFixer.FixTypes.ENTITY, - entityTag.asBinaryTag(), - dataVersion - )); - //FAWE end - } - - EntityType entityType = EntityTypes.get(id); - if (entityType != null) { - Location location = NBTConversions.toLocation( - clipboard, - requireTag(tags, "Pos", ListTag.class), - requireTag(tags, "Rotation", ListTag.class) - ); - BaseEntity state = new BaseEntity(entityType, entityTag); - clipboard.createEntity(location, state); - } else { - LOGGER.warn("Unknown entity when pasting schematic: " + id); - } - } - } - - @Override - public void close() throws IOException { - inputStream.close(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java deleted file mode 100644 index 2a10e9f4b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.extent.clipboard.io; - -import com.fastasyncworldedit.core.Fawe; -import com.google.common.collect.Maps; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTOutputStream; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Writes schematic files using the Sponge schematic format. - * - * @deprecated Slow, resource intensive, but sometimes safer than using the recommended - * {@link com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter}. - * Avoid using large clipboards to create schematics with this writer. - */ -@Deprecated -public class SpongeSchematicWriter implements ClipboardWriter { - - private static final int CURRENT_VERSION = 2; - - private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE; - private final NBTOutputStream outputStream; - - /** - * Create a new schematic writer. - * - * @param outputStream the output stream to write to - */ - public SpongeSchematicWriter(NBTOutputStream outputStream) { - checkNotNull(outputStream); - this.outputStream = outputStream; - } - - @Override - public void write(Clipboard clipboard) throws IOException { - //FAWE start - ensure clipboard is flushed in case of using clipboard-on-disk. Maintains allowing of the same code - // between upstream and FAWE - clipboard.flush(); - //FAWE end - // For now always write the latest version. Maybe provide support for earlier if more appear. - outputStream.writeNamedTag("Schematic", new CompoundTag(write2(clipboard))); - } - - /** - * Writes a version 2 schematic file. - * - * @param clipboard The clipboard - * @return The schematic map - */ - private Map write2(Clipboard clipboard) { - Region region = clipboard.getRegion(); - BlockVector3 origin = clipboard.getOrigin(); - BlockVector3 min = region.getMinimumPoint(); - BlockVector3 offset = min.subtract(origin); - int width = region.getWidth(); - int height = region.getHeight(); - int length = region.getLength(); - - if (width > MAX_SIZE) { - throw new IllegalArgumentException("Width of region too large for a .schematic"); - } - if (height > MAX_SIZE) { - throw new IllegalArgumentException("Height of region too large for a .schematic"); - } - if (length > MAX_SIZE) { - throw new IllegalArgumentException("Length of region too large for a .schematic"); - } - - Map schematic = new HashMap<>(); - schematic.put("Version", new IntTag(CURRENT_VERSION)); - schematic.put("DataVersion", new IntTag( - WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion())); - - Map metadata = new HashMap<>(); - metadata.put("WEOffsetX", new IntTag(offset.getBlockX())); - metadata.put("WEOffsetY", new IntTag(offset.getBlockY())); - metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ())); - metadata.put("FAWEVersion", new IntTag(Fawe.instance().getVersion().build)); - - schematic.put("Metadata", new CompoundTag(metadata)); - - schematic.put("Width", new ShortTag((short) width)); - schematic.put("Height", new ShortTag((short) height)); - schematic.put("Length", new ShortTag((short) length)); - - // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' - schematic.put("Offset", new IntArrayTag(new int[]{ - min.getBlockX(), - min.getBlockY(), - min.getBlockZ(), - })); - - int paletteMax = 0; - Map palette = new HashMap<>(); - - List tileEntities = new ArrayList<>(); - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length); - - for (int y = 0; y < height; y++) { - int y0 = min.getBlockY() + y; - for (int z = 0; z < length; z++) { - int z0 = min.getBlockZ() + z; - for (int x = 0; x < width; x++) { - int x0 = min.getBlockX() + x; - BlockVector3 point = BlockVector3.at(x0, y0, z0); - BaseBlock block = clipboard.getFullBlock(point); - if (block.getNbtData() != null) { - Map values = new HashMap<>(block.getNbtData().getValue()); - - values.remove("id"); // Remove 'id' if it exists. We want 'Id' - - // Positions are kept in NBT, we don't want that. - values.remove("x"); - values.remove("y"); - values.remove("z"); - - values.put("Id", new StringTag(block.getNbtId())); - values.put("Pos", new IntArrayTag(new int[]{x, y, z})); - - tileEntities.add(new CompoundTag(values)); - } - - String blockKey = block.toImmutableState().getAsString(); - int blockId; - if (palette.containsKey(blockKey)) { - blockId = palette.get(blockKey); - } else { - blockId = paletteMax; - palette.put(blockKey, blockId); - paletteMax++; - } - - while ((blockId & -128) != 0) { - buffer.write(blockId & 127 | 128); - blockId >>>= 7; - } - buffer.write(blockId); - } - } - } - - schematic.put("PaletteMax", new IntTag(paletteMax)); - - Map paletteTag = new HashMap<>(); - palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value))); - - schematic.put("Palette", new CompoundTag(paletteTag)); - schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray())); - schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities)); - - // version 2 stuff - if (clipboard.hasBiomes()) { - writeBiomes(clipboard, schematic); - } - - if (!clipboard.getEntities().isEmpty()) { - writeEntities(clipboard, schematic); - } - - return schematic; - } - - private void writeBiomes(Clipboard clipboard, Map schematic) { - BlockVector3 min = clipboard.getMinimumPoint(); - int width = clipboard.getRegion().getWidth(); - int length = clipboard.getRegion().getLength(); - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * length); - - int paletteMax = 0; - Map palette = new HashMap<>(); - - for (int z = 0; z < length; z++) { - int z0 = min.getBlockZ() + z; - for (int x = 0; x < width; x++) { - int x0 = min.getBlockX() + x; - BlockVector3 pt = BlockVector3.at(x0, min.getBlockY(), z0); - BiomeType biome = clipboard.getBiome(pt); - - String biomeKey = biome.getId(); - int biomeId; - if (palette.containsKey(biomeKey)) { - biomeId = palette.get(biomeKey); - } else { - biomeId = paletteMax; - palette.put(biomeKey, biomeId); - paletteMax++; - } - - while ((biomeId & -128) != 0) { - buffer.write(biomeId & 127 | 128); - biomeId >>>= 7; - } - buffer.write(biomeId); - } - } - - schematic.put("BiomePaletteMax", new IntTag(paletteMax)); - - Map paletteTag = new HashMap<>(); - palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value))); - - schematic.put("BiomePalette", new CompoundTag(paletteTag)); - schematic.put("BiomeData", new ByteArrayTag(buffer.toByteArray())); - } - - private void writeEntities(Clipboard clipboard, Map schematic) { - List entities = clipboard.getEntities().stream().map(e -> { - BaseEntity state = e.getState(); - if (state == null) { - return null; - } - Map values = Maps.newHashMap(); - CompoundTag rawData = state.getNbtData(); - if (rawData != null) { - values.putAll(rawData.getValue()); - } - values.remove("id"); - values.put("Id", new StringTag(state.getType().getId())); - final Location location = e.getLocation(); - values.put("Pos", writeVector(location.toVector())); - values.put("Rotation", writeRotation(location)); - - return new CompoundTag(values); - }).filter(Objects::nonNull).collect(Collectors.toList()); - if (entities.isEmpty()) { - return; - } - schematic.put("Entities", new ListTag(CompoundTag.class, entities)); - } - - @Override - public void close() throws IOException { - outputStream.close(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java index 826967400..d4b7347f2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java @@ -19,21 +19,16 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.CompoundTagBuilder; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler { @@ -55,17 +50,19 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler } @Override - public > boolean isAffectedBlock(B block) { - return block.getBlockType() == BlockTypes.WHITE_BANNER - || block.getBlockType() == BlockTypes.WHITE_WALL_BANNER; - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { - Tag typeTag = values.get("Base"); - if (typeTag instanceof IntTag) { + public BaseBlock updateNbt(BaseBlock block) { + var blockType = block.getBlockType(); + if (blockType != BlockTypes.WHITE_BANNER && blockType != BlockTypes.WHITE_WALL_BANNER) { + return block; + } + var nbt = block.getNbt(); + if (nbt == null) { + return block; + } + LinIntTag typeTag = nbt.findTag("Base", LinTagType.intTag()); + if (typeTag != null) { boolean isWall = block.getBlockType() == BlockTypes.WHITE_WALL_BANNER; - String bannerType = convertBannerType(((IntTag) typeTag).getValue(), isWall); + String bannerType = convertBannerType(typeTag.valueAsInt(), isWall); if (bannerType != null) { BlockType type = BlockTypes.get("minecraft:" + bannerType); if (type != null) { @@ -79,29 +76,25 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler state = state.with(rotationProp, block.getState(RotationProperty)); } - values.remove("Base"); + var nbtBuilder = nbt.toBuilder(); + nbtBuilder.remove("Base"); - Tag patternsTag = values.get("Patterns"); - if (patternsTag instanceof ListTag) { - List tempList = new ArrayList<>(); - for (Tag pattern : ((ListTag) patternsTag).getValue()) { - if (pattern instanceof CompoundTag) { - Map patternMap = ((CompoundTag) pattern).getValue(); - Tag colorTag = patternMap.get("Color"); - - CompoundTagBuilder builder = CompoundTagBuilder.create(); - builder.putAll(patternMap); - if (colorTag instanceof IntTag) { - builder.putInt("Color", 15 - ((IntTag) colorTag).getValue()); - } - tempList.add(builder.build()); + var patternsTag = nbt.findListTag("Patterns", LinTagType.compoundTag()); + if (patternsTag != null) { + var newPatterns = LinListTag.builder(LinTagType.compoundTag()); + for (LinCompoundTag pattern : patternsTag.value()) { + LinIntTag color = pattern.findTag("Color", LinTagType.intTag()); + if (color != null) { + newPatterns.add(pattern.toBuilder() + .putInt("Color", 15 - color.valueAsInt()) + .build()); } else { - tempList.add(pattern); + newPatterns.add(pattern); } } - values.put("Patterns", new ListTag(((ListTag) patternsTag).getType(), tempList)); + nbtBuilder.put("Patterns", newPatterns.build()); } - return state; + return state.toBaseBlock(nbtBuilder.build()); } } } @@ -109,58 +102,27 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler } private static String convertBannerType(int oldType, boolean isWall) { - String color; - switch (oldType) { - case 0: - color = "black"; - break; - case 1: - color = "red"; - break; - case 2: - color = "green"; - break; - case 3: - color = "brown"; - break; - case 4: - color = "blue"; - break; - case 5: - color = "purple"; - break; - case 6: - color = "cyan"; - break; - case 7: - color = "light_gray"; - break; - case 8: - color = "gray"; - break; - case 9: - color = "pink"; - break; - case 10: - color = "lime"; - break; - case 11: - color = "yellow"; - break; - case 12: - color = "light_blue"; - break; - case 13: - color = "magenta"; - break; - case 14: - color = "orange"; - break; - case 15: - color = "white"; - break; - default: - return null; + String color = switch (oldType) { + case 0 -> "black"; + case 1 -> "red"; + case 2 -> "green"; + case 3 -> "brown"; + case 4 -> "blue"; + case 5 -> "purple"; + case 6 -> "cyan"; + case 7 -> "light_gray"; + case 8 -> "gray"; + case 9 -> "pink"; + case 10 -> "lime"; + case 11 -> "yellow"; + case 12 -> "light_blue"; + case 13 -> "magenta"; + case 14 -> "orange"; + case 15 -> "white"; + default -> null; + }; + if (color == null) { + return null; } return color + (isWall ? "_wall_banner" : "_banner"); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java index eea18f8df..c8c26cc91 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java @@ -19,18 +19,15 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; +import org.enginehub.linbus.tree.LinTagType; -import java.util.Map; - -@SuppressWarnings("") public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler { private static final Property FACING_PROPERTY; @@ -51,92 +48,63 @@ public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler { } @Override - public > boolean isAffectedBlock(B block) { - return block.getBlockType() == BlockTypes.RED_BED; - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { - Tag typeTag = values.get("color"); - if (typeTag instanceof IntTag) { - String bedType = convertBedType(((IntTag) typeTag).getValue()); - if (bedType != null) { - BlockType type = BlockTypes.get("minecraft:" + bedType); - if (type != null) { - BlockState state = type.getDefaultState(); - - Property facingProp = type.getProperty("facing"); - state = state.with(facingProp, block.getState(FACING_PROPERTY)); - - Property occupiedProp = type.getProperty("occupied"); - state = state.with(occupiedProp, false); - - Property partProp = type.getProperty("part"); - state = state.with(partProp, block.getState(PART_PROPERTY)); - - values.remove("color"); - return state; - } - } + public BaseBlock updateNbt(BaseBlock block) { + if (block.getBlockType() != BlockTypes.RED_BED) { + return block; } - return block; + var tag = block.getNbt(); + if (tag == null) { + return block; + } + var typeTag = tag.findTag("color", LinTagType.intTag()); + if (typeTag == null) { + return block; + } + String bedType = convertBedType(typeTag.valueAsInt()); + if (bedType == null) { + return block; + } + BlockType type = BlockTypes.get("minecraft:" + bedType); + if (type == null) { + return block; + } + BlockState state = type.getDefaultState(); + + Property facingProp = type.getProperty("facing"); + state = state.with(facingProp, block.getState(FACING_PROPERTY)); + + Property occupiedProp = type.getProperty("occupied"); + state = state.with(occupiedProp, false); + + Property partProp = type.getProperty("part"); + state = state.with(partProp, block.getState(PART_PROPERTY)); + + var newTag = tag.toBuilder(); + newTag.remove("color"); + return state.toBaseBlock(LazyReference.computed(newTag.build())); } private String convertBedType(int oldType) { - String color; - switch (oldType) { - case 0: - color = "white"; - break; - case 1: - color = "orange"; - break; - case 2: - color = "magenta"; - break; - case 3: - color = "light_blue"; - break; - case 4: - color = "yellow"; - break; - case 5: - color = "lime"; - break; - case 6: - color = "pink"; - break; - case 7: - color = "gray"; - break; - case 8: - color = "light_gray"; - break; - case 9: - color = "cyan"; - break; - case 10: - color = "purple"; - break; - case 11: - color = "blue"; - break; - case 12: - color = "brown"; - break; - case 13: - color = "green"; - break; - case 14: - color = "red"; - break; - case 15: - color = "black"; - break; - default: - return null; - } - return color + "_bed"; + String color = switch (oldType) { + case 0 -> "white"; + case 1 -> "orange"; + case 2 -> "magenta"; + case 3 -> "light_blue"; + case 4 -> "yellow"; + case 5 -> "lime"; + case 6 -> "pink"; + case 7 -> "gray"; + case 8 -> "light_gray"; + case 9 -> "cyan"; + case 10 -> "purple"; + case 11 -> "blue"; + case 12 -> "brown"; + case 13 -> "green"; + case 14 -> "red"; + case 15 -> "black"; + default -> null; + }; + return color == null ? null : color + "_bed"; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/EntityNBTCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/EntityNBTCompatibilityHandler.java index 6fcc6f422..cfd82833d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/EntityNBTCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/EntityNBTCompatibilityHandler.java @@ -20,12 +20,48 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.world.entity.EntityType; +import org.enginehub.linbus.tree.LinCompoundTag; public interface EntityNBTCompatibilityHandler { - boolean isAffectedEntity(EntityType type, CompoundTag entityTag); + /** + * Check if this is an entity affected by this handler. + * + * @deprecated this was never used, just return the same tag from + * {@link #updateNbt(EntityType, LinCompoundTag)} if it's not affected + */ + @Deprecated + default boolean isAffectedEntity(EntityType type, CompoundTag entityTag) { + var original = entityTag.toLinTag(); + var updated = updateNbt(type, original); + return !original.equals(updated); + } - CompoundTag updateNBT(EntityType type, CompoundTag entityTag); + @Deprecated + default CompoundTag updateNBT(EntityType type, CompoundTag entityTag) { + return new CompoundTag(updateNbt(type, entityTag.toLinTag())); + } + /** + * Given an entity type and data, update the data if needed. + * + * @param type the entity type + * @param entityTag the entity tag + * @return the updated tag, or the same tag if no update was needed + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @SuppressWarnings("deprecation") + @NonAbstractForCompatibility( + delegateName = "updateNBT", + delegateParams = { EntityType.class, CompoundTag.class } + ) + default LinCompoundTag updateNbt(EntityType type, LinCompoundTag entityTag) { + DeprecationUtil.checkDelegatingOverride(getClass()); + + return updateNBT(type, new CompoundTag(entityTag)).toLinTag(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/FlowerPotCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/FlowerPotCompatibilityHandler.java index 974000762..803b6c237 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/FlowerPotCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/FlowerPotCompatibilityHandler.java @@ -19,72 +19,57 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; - -import java.util.Map; +import org.enginehub.linbus.tree.LinTagType; public class FlowerPotCompatibilityHandler implements NBTCompatibilityHandler { @Override - public > boolean isAffectedBlock(B block) { - return block.getBlockType() == BlockTypes.FLOWER_POT; - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { - Tag item = values.get("Item"); - if (item instanceof StringTag) { - String id = ((StringTag) item).getValue(); - if (id.isEmpty()) { - return BlockTypes.FLOWER_POT.getDefaultState(); - } - int data = 0; - Tag dataTag = values.get("Data"); - if (dataTag instanceof IntTag) { - data = ((IntTag) dataTag).getValue(); - } - BlockState newState = convertLegacyBlockType(id, data); - if (newState != null) { - values.clear(); - return newState; - } + public BaseBlock updateNbt(BaseBlock block) { + if (block.getBlockType() != BlockTypes.FLOWER_POT) { + return block; } - return block; + var tag = block.getNbt(); + if (tag == null) { + return block; + } + var item = tag.findTag("Item", LinTagType.stringTag()); + if (item == null) { + return block; + } + String id = item.value(); + if (id.isEmpty()) { + return BlockTypes.FLOWER_POT.getDefaultState().toBaseBlock(); + } + int data = 0; + var dataTag = tag.findTag("Data", LinTagType.intTag()); + if (dataTag != null) { + data = dataTag.valueAsInt(); + } + BlockState newState = convertLegacyBlockType(id, data); + return newState != null ? newState.toBaseBlock() : block; } private BlockState convertLegacyBlockType(String id, int data) { - int newId = 0; - switch (id) { - case "minecraft:red_flower": - newId = 38; // now poppy - break; - case "minecraft:yellow_flower": - newId = 37; // now dandelion - break; - case "minecraft:sapling": - newId = 6; // oak_sapling - break; - case "minecraft:deadbush": - case "minecraft:tallgrass": - newId = 31; // dead_bush with fern and grass (not 32!) - break; - default: - break; - } + int newId = switch (id) { + case "minecraft:red_flower" -> 38; // now poppy + case "minecraft:yellow_flower" -> 37; // now dandelion + case "minecraft:sapling" -> 6; // oak_sapling + case "minecraft:deadbush", "minecraft:tallgrass" -> + 31; // dead_bush with fern and grass (not 32!) + default -> 0; + }; String plantedName = null; if (newId == 0 && id.startsWith("minecraft:")) { plantedName = id.substring(10); } else { BlockState plantedWithData = LegacyMapper.getInstance().getBlockFromLegacy(newId, data); if (plantedWithData != null) { - plantedName = plantedWithData.getBlockType().getId().substring(10); // remove "minecraft:" + plantedName = plantedWithData.getBlockType().id().substring(10); // remove "minecraft:" } } if (plantedName != null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NBTCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NBTCompatibilityHandler.java index b7093dd4d..a2d32ea93 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NBTCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NBTCompatibilityHandler.java @@ -19,15 +19,80 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; +import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; +import java.util.HashMap; import java.util.Map; public interface NBTCompatibilityHandler { - > boolean isAffectedBlock(B block); + /** + * Check if this is a block affected by this handler. + * + * @deprecated this is handled by {@link #updateNbt(BaseBlock)} now + */ + @Deprecated + default > boolean isAffectedBlock(B block) { + BaseBlock state = block.toBaseBlock(); + BaseBlock updated = updateNbt(state); + return state != updated; + } - > BlockStateHolder updateNBT(B block, Map values); + @Deprecated + default > BlockStateHolder updateNBT(B block, Map> values) { + BaseBlock changed = updateNbt(block.toBaseBlock(LazyReference.from(() -> { + var builder = LinCompoundTag.builder(); + for (var entry : values.entrySet()) { + builder.put(entry.getKey(), entry.getValue().toLinTag()); + } + return builder.build(); + }))); + CompoundTag data = changed.getNbtData(); + values.clear(); + if (data != null) { + values.putAll(data.getValue()); + } + return changed; + } + + /** + * Given a block, update the block's NBT. The NBT may be {@code null}. + * + * @param block the block to update + * @return the updated block, or the same block if no change is necessary + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "updateNBT", + delegateParams = { BlockStateHolder.class, Map.class } + ) + @SuppressWarnings("deprecated") + default BaseBlock updateNbt(BaseBlock block) { + DeprecationUtil.checkDelegatingOverride(getClass()); + if (!isAffectedBlock(block)) { + return block; + } + if (block.getNbt() == null) { + return block; + } + @SuppressWarnings("deprecation") + Map> values = new HashMap<>(new CompoundTag(block.getNbt()).getValue()); + BlockStateHolder changedBlock = updateNBT(block, values); + return changedBlock.toBaseBlock(LazyReference.from(() -> { + var builder = LinCompoundTag.builder(); + for (var entry : values.entrySet()) { + builder.put(entry.getKey(), entry.getValue().toLinTag()); + } + return builder.build(); + })); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NoteBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NoteBlockCompatibilityHandler.java index 508e84280..04190197e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NoteBlockCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/NoteBlockCompatibilityHandler.java @@ -19,18 +19,15 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.registry.state.IntegerProperty; import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.Map; +import org.enginehub.linbus.tree.LinTagType; public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler { - private static final IntegerProperty NoteProperty; + private static final IntegerProperty NOTE_PROPERTY; static { IntegerProperty temp; @@ -39,27 +36,25 @@ public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler { } catch (NullPointerException | IllegalArgumentException | ClassCastException e) { temp = null; } - NoteProperty = temp; + NOTE_PROPERTY = temp; } @Override - public > boolean isAffectedBlock(B block) { - return NoteProperty != null && block.getBlockType() == BlockTypes.NOTE_BLOCK; - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { + public BaseBlock updateNbt(BaseBlock block) { + if (NOTE_PROPERTY == null || block.getBlockType() != BlockTypes.NOTE_BLOCK) { + return block; + } + var tag = block.getNbt(); + if (tag == null) { + return block; + } // note that instrument was not stored (in state or nbt) previously. // it will be updated to the block below when it gets set into the world for the first time - Tag noteTag = values.get("note"); - if (noteTag instanceof ByteTag) { - Byte note = ((ByteTag) noteTag).getValue(); - if (note != null) { - values.clear(); - return block.with(NoteProperty, (int) note).toImmutableState(); - } + var noteTag = tag.findTag("note", LinTagType.byteTag()); + if (noteTag == null) { + return block; } - return block; + return block.with(NOTE_PROPERTY, (int) noteTag.valueAsByte()).toBaseBlock(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/Pre13HangingCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/Pre13HangingCompatibilityHandler.java index 25457042c..f0bea016f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/Pre13HangingCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/Pre13HangingCompatibilityHandler.java @@ -19,41 +19,31 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.CompoundTagBuilder; import com.sk89q.worldedit.internal.helper.MCDirections; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.entity.EntityType; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinNumberTag; public class Pre13HangingCompatibilityHandler implements EntityNBTCompatibilityHandler { @Override - public boolean isAffectedEntity(EntityType type, CompoundTag tag) { + public LinCompoundTag updateNbt(EntityType type, LinCompoundTag tag) { if (!type.getId().startsWith("minecraft:")) { - return false; + return tag; } - boolean hasLegacyDirection = tag.containsKey("Dir") || tag.containsKey("Direction"); - boolean hasFacing = tag.containsKey("Facing"); - return hasLegacyDirection || hasFacing; - } - - @Override - public CompoundTag updateNBT(EntityType type, CompoundTag tag) { - boolean hasLegacyDir = tag.containsKey("Dir"); - boolean hasLegacyDirection = tag.containsKey("Direction"); - boolean hasPre113Facing = tag.containsKey("Facing"); Direction newDirection; - if (hasLegacyDir) { - newDirection = MCDirections.fromPre13Hanging(MCDirections.fromLegacyHanging((byte) tag.asInt("Dir"))); - } else if (hasLegacyDirection) { - newDirection = MCDirections.fromPre13Hanging(tag.asInt("Direction")); - } else if (hasPre113Facing) { - newDirection = MCDirections.fromPre13Hanging(tag.asInt("Facing")); + if (tag.value().get("Dir") instanceof LinNumberTag legacyDir) { + newDirection = MCDirections.fromPre13Hanging(MCDirections.fromLegacyHanging(legacyDir.value().byteValue())); + } else if (tag.value().get("Direction") instanceof LinNumberTag legacyDirection) { + newDirection = MCDirections.fromPre13Hanging(legacyDirection.value().intValue()); + } else if (tag.value().get("Facing") instanceof LinNumberTag legacyFacing) { + newDirection = MCDirections.fromPre13Hanging(legacyFacing.value().intValue()); } else { return tag; } byte hangingByte = (byte) MCDirections.toHanging(newDirection); - CompoundTagBuilder builder = tag.createBuilder(); + var builder = tag.toBuilder(); builder.putByte("Facing", hangingByte); return builder.build(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java index d2dd4f5a8..24c5de232 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java @@ -24,50 +24,52 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.internal.util.DeprecationUtil; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -import java.util.Map; +import com.sk89q.worldedit.world.block.BaseBlock; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; public class SignCompatibilityHandler implements NBTCompatibilityHandler { @Override - public > boolean isAffectedBlock(B block) { - return DeprecationUtil.isSign(block.getBlockType()); - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { + public BaseBlock updateNbt(BaseBlock block) { + if (!DeprecationUtil.isSign(block.getBlockType())) { + return block; + } + var tag = block.getNbt(); + if (tag == null) { + return block; + } + var newTag = tag.toBuilder(); for (int i = 0; i < 4; ++i) { String key = "Text" + (i + 1); - Tag value = values.get(key); - if (value instanceof StringTag) { - String storedString = ((StringTag) value).getValue(); - JsonElement jsonElement = null; - if (storedString != null && storedString.startsWith("{")) { - try { - jsonElement = new JsonParser().parse(storedString); - } catch (JsonSyntaxException ex) { - // ignore: jsonElement will be null in the next check - } - } - if (jsonElement == null) { - jsonElement = new JsonPrimitive(storedString == null ? "" : storedString); - } - if (jsonElement.isJsonObject()) { - continue; - } - - if (jsonElement.isJsonNull()) { - jsonElement = new JsonPrimitive(""); - } - - JsonObject jsonTextObject = new JsonObject(); - jsonTextObject.add("text", jsonElement); - values.put("Text" + (i + 1), new StringTag(jsonTextObject.toString())); + var value = tag.findTag(key, LinTagType.stringTag()); + if (value == null) { + continue; } + String storedString = value.value(); + JsonElement jsonElement = null; + if (storedString.startsWith("{")) { + try { + jsonElement = JsonParser.parseString(storedString); + } catch (JsonSyntaxException ex) { + // ignore: jsonElement will be null in the next check + } + } + if (jsonElement == null) { + jsonElement = new JsonPrimitive(storedString); + } + if (jsonElement.isJsonObject()) { + continue; + } + + if (jsonElement.isJsonNull()) { + jsonElement = new JsonPrimitive(""); + } + + JsonObject jsonTextObject = new JsonObject(); + jsonTextObject.add("text", jsonElement); + newTag.put("Text" + (i + 1), LinStringTag.of(jsonTextObject.toString())); } return block; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SkullBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SkullBlockCompatibilityHandler.java index f00622561..6d5158208 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SkullBlockCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SkullBlockCompatibilityHandler.java @@ -19,20 +19,17 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.Map; +import org.enginehub.linbus.tree.LinTagType; public class SkullBlockCompatibilityHandler implements NBTCompatibilityHandler { - private static final Property FacingProperty; + private static final Property FACING_PROPERTY; static { Property tempFacing; @@ -41,61 +38,70 @@ public class SkullBlockCompatibilityHandler implements NBTCompatibilityHandler { } catch (NullPointerException | IllegalArgumentException | ClassCastException e) { tempFacing = null; } - FacingProperty = tempFacing; + FACING_PROPERTY = tempFacing; } @Override - public > boolean isAffectedBlock(B block) { - return block.getBlockType() == BlockTypes.SKELETON_SKULL - || block.getBlockType() == BlockTypes.SKELETON_WALL_SKULL; - } - - @Override - public > BlockStateHolder updateNBT(B block, Map values) { - boolean isWall = block.getBlockType() == BlockTypes.SKELETON_WALL_SKULL; - Tag typeTag = values.get("SkullType"); - if (typeTag instanceof ByteTag) { - String skullType = convertSkullType(((ByteTag) typeTag).getValue(), isWall); - if (skullType != null) { - BlockType type = BlockTypes.get("minecraft:" + skullType); - if (type != null) { - BlockState state = type.getDefaultState(); - if (isWall) { - Property newProp = type.getProperty("facing"); - state = state.with(newProp, block.getState(FacingProperty)); - } else { - Tag rotTag = values.get("Rot"); - if (rotTag instanceof ByteTag) { - Property newProp = type.getProperty("rotation"); - state = state.with(newProp, (int) ((ByteTag) rotTag).getValue()); - } - } - values.remove("SkullType"); - values.remove("Rot"); - return state; - } + public BaseBlock updateNbt(BaseBlock block) { + var blockType = block.getBlockType(); + boolean isWall = blockType == BlockTypes.SKELETON_WALL_SKULL; + if (blockType != BlockTypes.SKELETON_SKULL && !isWall) { + return block; + } + if (FACING_PROPERTY == null) { + return block; + } + var tag = block.getNbt(); + if (tag == null) { + return block; + } + var typeTag = tag.findTag("SkullType", LinTagType.byteTag()); + if (typeTag == null) { + return block; + } + String skullType = convertSkullType(typeTag.valueAsByte(), isWall); + if (skullType == null) { + return block; + } + BlockType type = BlockTypes.get("minecraft:" + skullType); + if (type == null) { + return block; + } + BlockState state = type.getDefaultState(); + if (isWall) { + Property newProp = type.getProperty("facing"); + state = state.with(newProp, block.getState(FACING_PROPERTY)); + } else { + var rotTag = tag.findTag("Rot", LinTagType.byteTag()); + if (rotTag != null) { + Property newProp = type.getProperty("rotation"); + state = state.with(newProp, (int) rotTag.valueAsByte()); } } - return block; + var newTag = tag.toBuilder() + .remove("SkullType") + .remove("Rot") + .build(); + return state.toBaseBlock(newTag); } - private String convertSkullType(Byte oldType, boolean isWall) { - switch (oldType) { - case 0: - return isWall ? "skeleton_wall_skull" : "skeleton_skull"; - case 1: - return isWall ? "wither_skeleton_wall_skull" : "wither_skeleton_skull"; - case 2: - return isWall ? "zombie_wall_head" : "zombie_head"; - case 3: - return isWall ? "player_wall_head" : "player_head"; - case 4: - return isWall ? "creeper_wall_head" : "creeper_head"; - case 5: - return isWall ? "dragon_wall_head" : "dragon_head"; - default: - return null; + private String convertSkullType(byte oldType, boolean isWall) { + record SkullData(String kind, String suffix) { } + + var skullData = switch (oldType) { + case 0 -> new SkullData("skeleton", "skull"); + case 1 -> new SkullData("wither_skeleton", "skull"); + case 2 -> new SkullData("zombie", "head"); + case 3 -> new SkullData("player", "head"); + case 4 -> new SkullData("creeper", "head"); + case 5 -> new SkullData("dragon", "head"); + default -> null; + }; + if (skullData == null) { + return null; + } + return skullData.kind + (isWall ? "_wall" : "") + "_" + skullData.suffix; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/BuiltInClipboardShareDestinations.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/BuiltInClipboardShareDestinations.java new file mode 100644 index 000000000..551ac5dd7 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/BuiltInClipboardShareDestinations.java @@ -0,0 +1,150 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.share; + +import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.util.arkitektonika.ArkitektonikaResponse; +import com.fastasyncworldedit.core.util.arkitektonika.ArkitektonikaSchematicUploader; +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.paste.EngineHubPaste; +import com.sk89q.worldedit.util.paste.PasteMetadata; + +import java.io.ByteArrayOutputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.function.Consumer; + +/** + * A collection of natively supported clipboard share destinations. + */ +public enum BuiltInClipboardShareDestinations implements ClipboardShareDestination { + + /** + * The EngineHub pastebin service, at https://paste.enginehub.org/ + */ + ENGINEHUB_PASTEBIN("enginehub_paste", "ehpaste") { + @Override + public String getName() { + return "EngineHub Paste"; + } + + @Override + public Consumer share(ClipboardShareMetadata metadata, ShareOutputProvider serializer) throws Exception { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + serializer.writeTo(outputStream); + + PasteMetadata pasteMetadata = new PasteMetadata(); + pasteMetadata.author = metadata.author(); + pasteMetadata.extension = metadata.format().getPrimaryFileExtension(); + pasteMetadata.name = metadata.name(); + EngineHubPaste pasteService = new EngineHubPaste(); + + URL url = pasteService.paste(new String( + Base64.getEncoder().encode(outputStream.toByteArray()), + StandardCharsets.UTF_8 + ), pasteMetadata).call(); + String urlString = url.toExternalForm() + ".schem"; + return actor -> actor.printInfo(TextComponent.of(urlString).clickEvent(ClickEvent.openUrl(urlString))); + } + + @Override + public ClipboardFormat getDefaultFormat() { + return BuiltInClipboardFormat.SPONGE_V2_SCHEMATIC; + } + + @Override + public boolean supportsFormat(ClipboardFormat format) { + return format == getDefaultFormat(); + } + }, + + //FAWE start - add arkitektonika + ARKITEKTONIKA("arkitektonika", "fawe") { + + private ArkitektonikaSchematicUploader uploader; + + @Override + public String getName() { + return "Arkitektonika"; + } + + @Override + public Consumer share(final ClipboardShareMetadata metadata, final ShareOutputProvider serializer) throws + Exception { + if (uploader == null) { + uploader = new ArkitektonikaSchematicUploader(Settings.settings().WEB.ARKITEKTONIKA_BACKEND_URL); + } + final ArkitektonikaResponse response = uploader.uploadBlocking(metadata, serializer); + final String downloadUrl = Settings.settings().WEB.ARKITEKTONIKA_DOWNLOAD_URL.replace("{key}", response.downloadKey()); + final String deletionUrl = Settings.settings().WEB.ARKITEKTONIKA_DELETE_URL.replace("{key}", response.deletionKey()); + return actor -> { + actor.print(Caption.of( + "worldedit.schematic.share.response.arkitektonika.download", + Caption.of("worldedit.schematic.share.response.arkitektonika.click-here") + .color(TextColor.GREEN).clickEvent(ClickEvent.openUrl(downloadUrl)) + )); + actor.print(Caption.of( + "worldedit.schematic.share.response.arkitektonika.delete", + Caption.of("worldedit.schematic.share.response.arkitektonika.click-here") + .color(TextColor.RED).clickEvent(ClickEvent.openUrl(deletionUrl)) + )); + }; + } + + @Override + public ClipboardFormat getDefaultFormat() { + return BuiltInClipboardFormat.FAST_V3; + } + + @Override + public boolean supportsFormat(final ClipboardFormat format) { + return format == BuiltInClipboardFormat.SPONGE_V2_SCHEMATIC || + format == BuiltInClipboardFormat.FAST_V3 || + format == BuiltInClipboardFormat.FAST_V2 || + format == BuiltInClipboardFormat.MCEDIT_SCHEMATIC; + } + }; + //FAWE end + + private final ImmutableSet aliases; + + BuiltInClipboardShareDestinations(String... aliases) { + this.aliases = ImmutableSet.copyOf(aliases); + } + + @Override + public ImmutableSet getAliases() { + return this.aliases; + } + + @Override + public String getName() { + return name(); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestination.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestination.java new file mode 100644 index 000000000..1b0cb9e21 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestination.java @@ -0,0 +1,72 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.share; + +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; + +import java.util.Set; +import java.util.function.Consumer; + +public interface ClipboardShareDestination { + + /** + * Gets the name of this share destination. + * + * @return The name + */ + String getName(); + + /** + * Get a set of aliases. + * + * @return a set of aliases + */ + Set getAliases(); + + /** + * Share a clipboard output stream and return a URL. + * + *

+ * The serialized schematic can be retrieved by providing an {@link java.io.OutputStream} to {@code serializer}. + *

+ * + * @param metadata The clipboard metadata + * @param serializer A function taking the {@link java.io.OutputStream} + * @return A consumer to provide the actor with the share results + * @throws Exception if it failed to share + */ + Consumer share(ClipboardShareMetadata metadata, ShareOutputProvider serializer) throws Exception; + + /** + * Gets the default clipboard format for this share destination. + * + * @return The default format + */ + ClipboardFormat getDefaultFormat(); + + /** + * Gets whether the share destination supports the given format. + * + * @param format The format + * @return If it's supported + */ + boolean supportsFormat(ClipboardFormat format); +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestinations.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestinations.java new file mode 100644 index 000000000..cf9b408f1 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareDestinations.java @@ -0,0 +1,80 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.share; + +import com.sk89q.worldedit.WorldEdit; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public class ClipboardShareDestinations { + + private static final Map aliasMap = new HashMap<>(); + private static final List registeredDestinations = new ArrayList<>(); + + public static void registerClipboardShareDestination(ClipboardShareDestination destination) { + checkNotNull(destination); + checkState(destination.supportsFormat(destination.getDefaultFormat()), "Destination must accept its default format"); + + for (String key : destination.getAliases()) { + String lowKey = key.toLowerCase(Locale.ROOT); + ClipboardShareDestination old = aliasMap.put(lowKey, destination); + if (old != null) { + aliasMap.put(lowKey, old); + WorldEdit.logger.warn(destination.getClass().getName() + " cannot override existing alias '" + lowKey + "' used by " + old.getClass().getName()); + } + } + registeredDestinations.add(destination); + } + + static { + for (BuiltInClipboardShareDestinations destination : BuiltInClipboardShareDestinations.values()) { + registerClipboardShareDestination(destination); + } + } + + /** + * Find the clipboard format named by the given alias. + * + * @param alias the alias + * @return the format, otherwise null if none is matched + */ + @Nullable + public static ClipboardShareDestination findByAlias(String alias) { + checkNotNull(alias); + return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim()); + } + + public static Collection getAll() { + return Collections.unmodifiableCollection(registeredDestinations); + } + + private ClipboardShareDestinations() { + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareMetadata.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareMetadata.java new file mode 100644 index 000000000..a670ea7cc --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ClipboardShareMetadata.java @@ -0,0 +1,32 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.share; + +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; + +/** + * Items of metadata about shared clipboards. + * + * @param format the format of the clipboard + * @param name the name of the clipboard + * @param author the author of the clipboard + */ +public record ClipboardShareMetadata(ClipboardFormat format, String name, String author) { +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ShareOutputProvider.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ShareOutputProvider.java new file mode 100644 index 000000000..6d7587925 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/share/ShareOutputProvider.java @@ -0,0 +1,37 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.share; + +import com.sk89q.worldedit.WorldEditException; + +import java.io.IOException; +import java.io.OutputStream; + +@FunctionalInterface +public interface ShareOutputProvider { + + /** + * Provides the share output to {@code stream}. + * + * @throws IOException if it failed + * @throws WorldEditException if WorldEdit failed to serialize to the stream + */ + void writeTo(OutputStream stream) throws IOException, WorldEditException; +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/ReaderUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/ReaderUtil.java new file mode 100644 index 000000000..5c4e90264 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/ReaderUtil.java @@ -0,0 +1,283 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.internal.util.VarIntIterator; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.DataFixer; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.entity.EntityType; +import com.sk89q.worldedit.world.entity.EntityTypes; +import com.sk89q.worldedit.world.storage.NBTConversions; +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkState; + +/** + * Common code shared between schematic readers. + */ +public class ReaderUtil { //FAWE - make public + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + static void checkSchematicVersion(int version, LinCompoundTag schematicTag) throws IOException { + int schematicVersion = getSchematicVersion(schematicTag); + + checkState( + version == schematicVersion, + "Schematic is not version %s, but %s", version, schematicVersion + ); + } + + public static int getSchematicVersion(LinCompoundTag schematicTag) throws IOException { + return schematicTag.getTag("Version", LinTagType.intTag()).valueAsInt(); + } + + static VersionedDataFixer getVersionedDataFixer( + LinCompoundTag schematic, Platform platform, + int liveDataVersion + ) { + //FAWE start - call fawe method without NBT component requirement + return getVersionedDataFixer(schematic.getTag("DataVersion", LinTagType.intTag()).valueAsInt(), platform, + liveDataVersion + ); + //FAWE end + } + + //FAWE start - make getVersionedDataFixer without schematic compound + public + public static VersionedDataFixer getVersionedDataFixer(int schematicDataVersion, Platform platform, int liveDataVersion) { + DataFixer fixer = null; + if (schematicDataVersion < 0) { + LOGGER.warn( + "Schematic has an unknown data version ({}). Data may be incompatible.", + schematicDataVersion + ); + } else if (schematicDataVersion > liveDataVersion) { + LOGGER.warn( + "Schematic was made in a newer Minecraft version ({} > {})." + + " Data may be incompatible.", + schematicDataVersion, liveDataVersion + ); + } else if (schematicDataVersion < liveDataVersion) { + fixer = platform.getDataFixer(); + if (fixer != null) { + LOGGER.debug( + "Schematic was made in an older Minecraft version ({} < {})," + + " will attempt DFU.", + schematicDataVersion, liveDataVersion + ); + } else { + LOGGER.info( + "Schematic was made in an older Minecraft version ({} < {})," + + " but DFU is not available. Data may be incompatible.", + schematicDataVersion, liveDataVersion + ); + } + } + return new VersionedDataFixer(schematicDataVersion, fixer); + } + //FAWE end + + static Map decodePalette( + LinCompoundTag paletteObject, VersionedDataFixer fixer + ) throws IOException { + Map palette = new HashMap<>(); + + ParserContext parserContext = new ParserContext(); + parserContext.setRestricted(false); + parserContext.setTryLegacy(false); + parserContext.setPreferringWildcard(false); + + for (var palettePart : paletteObject.value().entrySet()) { + if (!(palettePart.getValue() instanceof LinIntTag idTag)) { + throw new IOException("Invalid palette entry: " + palettePart); + } + int id = idTag.valueAsInt(); + String paletteName = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart.getKey()); + BlockState state; + try { + state = WorldEdit.getInstance().getBlockFactory().parseFromInput(paletteName, parserContext).toImmutableState(); + } catch (InputParseException e) { + LOGGER.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air."); + state = BlockTypes.AIR.getDefaultState(); + } + palette.put(id, state); + } + return palette; + } + + static void initializeClipboardFromBlocks( + Clipboard clipboard, Map palette, byte[] blocks, LinListTag tileEntities, + VersionedDataFixer fixer, boolean dataIsNested + ) throws IOException { + Map tileEntitiesMap = new HashMap<>(); + if (tileEntities != null) { + for (LinCompoundTag tileEntity : tileEntities.value()) { + final BlockVector3 pt = clipboard.getMinimumPoint().add( + decodeBlockVector3(tileEntity.getTag("Pos", LinTagType.intArrayTag())) + ); + LinCompoundTag.Builder values = extractData(dataIsNested, tileEntity); + values.putInt("x", pt.x()); + values.putInt("y", pt.y()); + values.putInt("z", pt.z()); + values.put("id", tileEntity.value().get("Id")); + if (fixer.isActive()) { + tileEntity = fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, values.build()); + } else { + tileEntity = values.build(); + } + tileEntitiesMap.put(pt, tileEntity); + } + } + + int width = clipboard.getRegion().getWidth(); + int length = clipboard.getRegion().getLength(); + + int index = 0; + for (VarIntIterator iter = new VarIntIterator(blocks); iter.hasNext(); index++) { + int nextBlockId = iter.nextInt(); + BlockState state = palette.get(nextBlockId); + BlockVector3 rawPos = decodePositionFromDataIndex(width, length, index); + try { + BlockVector3 offsetPos = clipboard.getMinimumPoint().add(rawPos); + LinCompoundTag tileEntity = tileEntitiesMap.get(offsetPos); + clipboard.setBlock(offsetPos, state.toBaseBlock(tileEntity)); + } catch (WorldEditException e) { + throw new IOException("Failed to load a block in the schematic", e); + } + } + } + + private static LinCompoundTag.Builder extractData(boolean dataIsNested, LinCompoundTag tag) { + if (dataIsNested) { + LinCompoundTag dataTag = tag.findTag("Data", LinTagType.compoundTag()); + return dataTag != null ? dataTag.toBuilder() : LinCompoundTag.builder(); + } else { + LinCompoundTag.Builder values = tag.toBuilder(); + values.remove("Id"); + values.remove("Pos"); + return values; + } + } + + static BlockVector3 decodePositionFromDataIndex(int width, int length, int index) { + // index = (y * width * length) + (z * width) + x + int y = index / (width * length); + int remainder = index - (y * width * length); + int z = remainder / width; + int x = remainder - z * width; + return BlockVector3.at(x, y, z); + } + + static BlockVector3 decodeBlockVector3(@Nullable LinIntArrayTag tag) throws IOException { + if (tag == null) { + return BlockVector3.ZERO; + } + int[] parts = tag.value(); + if (parts.length != 3) { + throw new IOException("Invalid block vector specified in schematic."); + } + return BlockVector3.at(parts[0], parts[1], parts[2]); + } + + static void readEntities( + BlockArrayClipboard clipboard, List entList, + VersionedDataFixer fixer, boolean positionIsRelative + ) { + if (entList.isEmpty()) { + return; + } + for (LinCompoundTag entityTag : entList) { + String id = entityTag.getTag("Id", LinTagType.stringTag()).value(); + LinCompoundTag.Builder values = extractData(positionIsRelative, entityTag); + LinCompoundTag dataTag = values.putString("id", id).build(); + dataTag = fixer.fixUp(DataFixer.FixTypes.ENTITY, dataTag); + + EntityType entityType = EntityTypes.get(id); + if (entityType != null) { + Location location = NBTConversions.toLocation( + clipboard, + entityTag.getListTag("Pos", LinTagType.doubleTag()), + dataTag.getListTag("Rotation", LinTagType.floatTag()) + ); + BaseEntity state = new BaseEntity(entityType, LazyReference.computed(dataTag)); + if (positionIsRelative) { + location = location.setPosition( + location.toVector().add(clipboard.getMinimumPoint().toVector3()) + ); + } + clipboard.createEntity(location, state); + } else { + LOGGER.warn("Unknown entity when pasting schematic: " + id); + } + } + } + + static Int2ObjectMap readBiomePalette(VersionedDataFixer fixer, LinCompoundTag paletteTag, Logger logger) throws + IOException { + Int2ObjectMap palette = new Int2ObjectLinkedOpenHashMap<>(paletteTag.value().size()); + for (var palettePart : paletteTag.value().entrySet()) { + String key = palettePart.getKey(); + key = fixer.fixUp(DataFixer.FixTypes.BIOME, key); + BiomeType biome = BiomeTypes.get(key); + if (biome == null) { + logger.warn("Unknown biome type :" + key + + " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?"); + } + if (!(palettePart.getValue() instanceof LinIntTag idTag)) { + throw new IOException("Biome mapped to non-Int tag."); + } + palette.put(idTag.valueAsInt(), biome); + } + return palette; + } + + private ReaderUtil() { + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV1Reader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV1Reader.java new file mode 100644 index 000000000..7574bfe4c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV1Reader.java @@ -0,0 +1,134 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.internal.Constants; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.block.BlockState; +import org.enginehub.linbus.stream.LinStream; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.IOException; +import java.util.Map; +import java.util.OptionalInt; + +/** + * Reads schematic files using the Sponge Schematic Specification (Version 1). + */ +public class SpongeSchematicV1Reader implements ClipboardReader { + + private final LinStream rootStream; + + public SpongeSchematicV1Reader(LinStream rootStream) { + this.rootStream = rootStream; + } + + @Override + public Clipboard read() throws IOException { + LinCompoundTag schematicTag = getBaseTag(); + ReaderUtil.checkSchematicVersion(1, schematicTag); + + return doRead(schematicTag); + } + + // For legacy SpongeSchematicReader, can be inlined in WorldEdit 8 + public static BlockArrayClipboard doRead(LinCompoundTag schematicTag) throws IOException { + final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + + // this is a relatively safe assumption unless someone imports a schematic from 1.12 + // e.g. sponge 7.1- + VersionedDataFixer fixer = new VersionedDataFixer(Constants.DATA_VERSION_MC_1_13_2, platform.getDataFixer()); + return readVersion1(schematicTag, fixer); + } + + @Override + public OptionalInt getDataVersion() { + try { + // Validate schematic version to be sure + ReaderUtil.checkSchematicVersion(1, getBaseTag()); + return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2); + } catch (IOException e) { + return OptionalInt.empty(); + } + } + + private LinCompoundTag getBaseTag() throws IOException { + return LinRootEntry.readFrom(rootStream).value(); + } + + static BlockArrayClipboard readVersion1(LinCompoundTag schematicTag, VersionedDataFixer fixer) throws IOException { + int width = schematicTag.getTag("Width", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + int height = schematicTag.getTag("Height", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + int length = schematicTag.getTag("Length", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + + BlockVector3 min = ReaderUtil.decodeBlockVector3(schematicTag.findTag("Offset", LinTagType.intArrayTag())); + + BlockVector3 offset = BlockVector3.ZERO; + LinCompoundTag metadataTag = schematicTag.findTag("Metadata", LinTagType.compoundTag()); + if (metadataTag != null) { + LinIntTag offsetX = metadataTag.findTag("WEOffsetX", LinTagType.intTag()); + if (offsetX != null) { + int offsetY = metadataTag.getTag("WEOffsetY", LinTagType.intTag()).valueAsInt(); + int offsetZ = metadataTag.getTag("WEOffsetZ", LinTagType.intTag()).valueAsInt(); + offset = BlockVector3.at(offsetX.valueAsInt(), offsetY, offsetZ); + } + } + + BlockVector3 origin = min.subtract(offset); + Region region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE)); + + LinIntTag paletteMaxTag = schematicTag.findTag("PaletteMax", LinTagType.intTag()); + LinCompoundTag paletteObject = schematicTag.getTag("Palette", LinTagType.compoundTag()); + if (paletteMaxTag != null && paletteObject.value().size() != paletteMaxTag.valueAsInt()) { + throw new IOException("Block palette size does not match expected size."); + } + + Map palette = ReaderUtil.decodePalette(paletteObject, fixer); + + byte[] blocks = schematicTag.getTag("BlockData", LinTagType.byteArrayTag()).value(); + + LinListTag tileEntities = schematicTag.findListTag("BlockEntities", LinTagType.compoundTag()); + if (tileEntities == null) { + tileEntities = schematicTag.findListTag("TileEntities", LinTagType.compoundTag()); + } + + BlockArrayClipboard clipboard = new BlockArrayClipboard(region); + clipboard.setOrigin(origin); + ReaderUtil.initializeClipboardFromBlocks(clipboard, palette, blocks, tileEntities, fixer, false); + return clipboard; + } + + @Override + public void close() throws IOException { + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Reader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Reader.java new file mode 100644 index 000000000..2cd7bb1e1 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Reader.java @@ -0,0 +1,144 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.internal.util.VarIntIterator; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.biome.BiomeType; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.stream.LinStream; +import org.enginehub.linbus.tree.LinByteArrayTag; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.IOException; +import java.util.OptionalInt; + +/** + * Reads schematic files using the Sponge Schematic Specification (Version 2). + */ +public class SpongeSchematicV2Reader implements ClipboardReader { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private final LinStream rootStream; + + public SpongeSchematicV2Reader(LinStream rootStream) { + this.rootStream = rootStream; + } + + @Override + public Clipboard read() throws IOException { + LinCompoundTag schematicTag = getBaseTag(); + ReaderUtil.checkSchematicVersion(2, schematicTag); + + return doRead(schematicTag); + } + + // For legacy SpongeSchematicReader, can be inlined in WorldEdit 8 + public static Clipboard doRead(LinCompoundTag schematicTag) throws IOException { + final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + int liveDataVersion = platform.getDataVersion(); + + VersionedDataFixer fixer = ReaderUtil.getVersionedDataFixer(schematicTag, platform, liveDataVersion); + BlockArrayClipboard clip = SpongeSchematicV1Reader.readVersion1(schematicTag, fixer); + return readVersion2(clip, schematicTag, fixer); + } + + @Override + public OptionalInt getDataVersion() { + try { + LinCompoundTag schematicTag = getBaseTag(); + ReaderUtil.checkSchematicVersion(2, schematicTag); + + int dataVersion = schematicTag.getTag("DataVersion", LinTagType.intTag()).valueAsInt(); + if (dataVersion < 0) { + return OptionalInt.empty(); + } + return OptionalInt.of(dataVersion); + } catch (IOException e) { + return OptionalInt.empty(); + } + } + + private LinCompoundTag getBaseTag() throws IOException { + return LinRootEntry.readFrom(rootStream).value(); + } + + private static Clipboard readVersion2( + BlockArrayClipboard version1, LinCompoundTag schematicTag, VersionedDataFixer fixer + ) throws IOException { + if (schematicTag.value().containsKey("BiomeData")) { + readBiomes2(version1, schematicTag, fixer); + } + LinListTag entities = schematicTag.findListTag("Entities", LinTagType.compoundTag()); + if (entities != null) { + ReaderUtil.readEntities(version1, entities.value(), fixer, false); + } + return version1; + } + + private static void readBiomes2( + BlockArrayClipboard clipboard, LinCompoundTag schematic, VersionedDataFixer fixer + ) throws IOException { + LinByteArrayTag dataTag = schematic.getTag("BiomeData", LinTagType.byteArrayTag()); + LinIntTag maxTag = schematic.getTag("BiomePaletteMax", LinTagType.intTag()); + LinCompoundTag paletteTag = schematic.getTag("BiomePalette", LinTagType.compoundTag()); + + if (maxTag.valueAsInt() != paletteTag.value().size()) { + throw new IOException("Biome palette size does not match expected size."); + } + + Int2ObjectMap palette = ReaderUtil.readBiomePalette(fixer, paletteTag, LOGGER); + + int width = clipboard.getDimensions().x(); + + byte[] biomes = dataTag.value(); + BlockVector3 min = clipboard.getMinimumPoint(); + int index = 0; + for (VarIntIterator iter = new VarIntIterator(biomes); iter.hasNext(); index++) { + int nextBiomeId = iter.nextInt(); + BiomeType type = palette.get(nextBiomeId); + // hack -- the x and y values from the 3d decode with length == 1 are equivalent + BlockVector3 hackDecode = ReaderUtil.decodePositionFromDataIndex(width, 1, index); + int x = hackDecode.x(); + int z = hackDecode.y(); + for (int y = 0; y < clipboard.getRegion().getHeight(); y++) { + clipboard.setBiome(min.add(x, y, z), type); + } + } + } + + @Override + public void close() throws IOException { + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Writer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Writer.java new file mode 100644 index 000000000..8504f0fe8 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV2Writer.java @@ -0,0 +1,255 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; +import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntMaps; +import org.enginehub.linbus.stream.LinBinaryIO; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * Writes schematic files using the Sponge Schematic Specification (Version 2). + */ +public class SpongeSchematicV2Writer implements ClipboardWriter { + + private static final int CURRENT_VERSION = 2; + + private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE; + private final DataOutputStream outputStream; + + public SpongeSchematicV2Writer(DataOutputStream outputStream) { + this.outputStream = outputStream; + } + + @Override + public void write(Clipboard clipboard) throws IOException { + //FAWE start - ensure clipboard is flushed in case of using clipboard-on-disk. Maintains allowing of the same code + // between upstream and FAWE + clipboard.flush(); + //FAWE end + LinBinaryIO.write(outputStream, new LinRootEntry("Schematic", write2(clipboard))); + } + + /** + * Writes a version 2 schematic file. + * + * @param clipboard The clipboard + * @return the schematic tag + */ + private LinCompoundTag write2(Clipboard clipboard) { + Region region = clipboard.getRegion(); + BlockVector3 origin = clipboard.getOrigin(); + BlockVector3 min = region.getMinimumPoint(); + BlockVector3 offset = min.subtract(origin); + int width = region.getWidth(); + int height = region.getHeight(); + int length = region.getLength(); + + if (width > MAX_SIZE) { + throw new IllegalArgumentException("Width of region too large for a .schematic"); + } + if (height > MAX_SIZE) { + throw new IllegalArgumentException("Height of region too large for a .schematic"); + } + if (length > MAX_SIZE) { + throw new IllegalArgumentException("Length of region too large for a .schematic"); + } + + LinCompoundTag.Builder schematic = LinCompoundTag.builder(); + schematic.putInt("Version", CURRENT_VERSION); + schematic.putInt("DataVersion", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion() + ); + + LinCompoundTag.Builder metadata = LinCompoundTag.builder(); + metadata.putInt("WEOffsetX", offset.x()); + metadata.putInt("WEOffsetY", offset.y()); + metadata.putInt("WEOffsetZ", offset.z()); + + LinCompoundTag.Builder worldEditSection = LinCompoundTag.builder(); + worldEditSection.putString("Version", WorldEdit.getVersion()); + worldEditSection.putString("EditingPlatform", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).id() + ); + worldEditSection.putIntArray("Offset", new int[]{offset.x(), offset.y(), offset.z()}); + + LinCompoundTag.Builder platformsSection = LinCompoundTag.builder(); + for (Platform platform : WorldEdit.getInstance().getPlatformManager().getPlatforms()) { + platformsSection.put(platform.id(), LinCompoundTag + .builder() + .putString("Name", platform.getPlatformName()) + .putString("Version", platform.getPlatformVersion()) + .build()); + } + worldEditSection.put("Platforms", platformsSection.build()); + + metadata.put("WorldEdit", worldEditSection.build()); + + schematic.put("Metadata", metadata.build()); + + schematic.putShort("Width", (short) width); + schematic.putShort("Height", (short) height); + schematic.putShort("Length", (short) length); + + // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' + schematic.putIntArray("Offset", new int[]{min.x(), min.y(), min.z(),}); + + int paletteMax = 0; + Object2IntMap palette = new Object2IntLinkedOpenHashMap<>(); + + LinListTag.Builder tileEntities = LinListTag.builder(LinTagType.compoundTag()); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length); + + for (int y = 0; y < height; y++) { + int y0 = min.y() + y; + for (int z = 0; z < length; z++) { + int z0 = min.z() + z; + for (int x = 0; x < width; x++) { + int x0 = min.x() + x; + BlockVector3 point = BlockVector3.at(x0, y0, z0); + BaseBlock block = clipboard.getFullBlock(point); + LinCompoundTag nbt = block.getNbt(); + if (nbt != null) { + LinCompoundTag.Builder values = nbt.toBuilder(); + + values.remove("id"); // Remove 'id' if it exists. We want 'Id' + + // Positions are kept in NBT, we don't want that. + values.remove("x"); + values.remove("y"); + values.remove("z"); + + values.putString("Id", block.getNbtId()); + values.putIntArray("Pos", new int[]{x, y, z}); + + tileEntities.add(values.build()); + } + + String blockKey = block.toImmutableState().getAsString(); + int blockId; + if (palette.containsKey(blockKey)) { + blockId = palette.getInt(blockKey); + } else { + blockId = paletteMax; + palette.put(blockKey, blockId); + paletteMax++; + } + + while ((blockId & -128) != 0) { + buffer.write(blockId & 127 | 128); + blockId >>>= 7; + } + buffer.write(blockId); + } + } + } + + schematic.putInt("PaletteMax", paletteMax); + + LinCompoundTag.Builder paletteTag = LinCompoundTag.builder(); + Object2IntMaps.fastForEach(palette, e -> paletteTag.putInt(e.getKey(), e.getIntValue())); + + schematic.put("Palette", paletteTag.build()); + schematic.putByteArray("BlockData", buffer.toByteArray()); + schematic.put("BlockEntities", tileEntities.build()); + + // version 2 stuff + if (clipboard.hasBiomes()) { + writeBiomes(clipboard, schematic); + } + + if (!clipboard.getEntities().isEmpty()) { + LinListTag value = WriterUtil.encodeEntities(clipboard, false); + if (value != null) { + schematic.put("Entities", value); + } + } + + return schematic.build(); + } + + private void writeBiomes(Clipboard clipboard, LinCompoundTag.Builder schematic) { + BlockVector3 min = clipboard.getMinimumPoint(); + int width = clipboard.getRegion().getWidth(); + int length = clipboard.getRegion().getLength(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * length); + + int paletteMax = 0; + Object2IntMap palette = new Object2IntLinkedOpenHashMap<>(); + + for (int z = 0; z < length; z++) { + int z0 = min.z() + z; + for (int x = 0; x < width; x++) { + int x0 = min.x() + x; + BlockVector3 pt = BlockVector3.at(x0, min.y(), z0); + BiomeType biome = clipboard.getBiome(pt); + + String biomeKey = biome.id(); + int biomeId; + if (palette.containsKey(biomeKey)) { + biomeId = palette.getInt(biomeKey); + } else { + biomeId = paletteMax; + palette.put(biomeKey, biomeId); + paletteMax++; + } + + while ((biomeId & -128) != 0) { + buffer.write(biomeId & 127 | 128); + biomeId >>>= 7; + } + buffer.write(biomeId); + } + } + + schematic.putInt("BiomePaletteMax", paletteMax); + + LinCompoundTag.Builder paletteTag = LinCompoundTag.builder(); + Object2IntMaps.fastForEach(palette, e -> paletteTag.putInt(e.getKey(), e.getIntValue())); + + schematic.put("BiomePalette", paletteTag.build()); + schematic.putByteArray("BiomeData", buffer.toByteArray()); + } + + @Override + public void close() throws IOException { + outputStream.close(); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java new file mode 100644 index 000000000..15032be82 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java @@ -0,0 +1,168 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.internal.util.VarIntIterator; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.stream.LinStream; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.IOException; +import java.util.Map; +import java.util.OptionalInt; + +/** + * Reads schematic files using the Sponge Schematic Specification. + */ +public class SpongeSchematicV3Reader implements ClipboardReader { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private final LinStream rootStream; + + public SpongeSchematicV3Reader(LinStream rootStream) { + this.rootStream = rootStream; + } + + @Override + public Clipboard read() throws IOException { + LinCompoundTag schematicTag = getBaseTag(); + ReaderUtil.checkSchematicVersion(3, schematicTag); + + final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + int liveDataVersion = platform.getDataVersion(); + + VersionedDataFixer fixer = ReaderUtil.getVersionedDataFixer(schematicTag, platform, liveDataVersion); + return readVersion3(schematicTag, fixer); + } + + @Override + public OptionalInt getDataVersion() { + try { + LinCompoundTag schematicTag = getBaseTag(); + ReaderUtil.checkSchematicVersion(3, schematicTag); + + int dataVersion = schematicTag.getTag("DataVersion", LinTagType.intTag()).valueAsInt(); + if (dataVersion < 0) { + return OptionalInt.empty(); + } + return OptionalInt.of(dataVersion); + } catch (IOException e) { + return OptionalInt.empty(); + } + } + + private LinCompoundTag getBaseTag() throws IOException { + return LinRootEntry.readFrom(rootStream).value().getTag("Schematic", LinTagType.compoundTag()); + } + + private Clipboard readVersion3(LinCompoundTag schematicTag, VersionedDataFixer fixer) throws IOException { + int width = schematicTag.getTag("Width", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + int height = schematicTag.getTag("Height", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + int length = schematicTag.getTag("Length", LinTagType.shortTag()).valueAsShort() & 0xFFFF; + + BlockVector3 offset = ReaderUtil.decodeBlockVector3(schematicTag.findTag("Offset", LinTagType.intArrayTag())); + + BlockVector3 origin = BlockVector3.ZERO; + LinCompoundTag metadataTag = schematicTag.findTag("Metadata", LinTagType.compoundTag()); + if (metadataTag != null) { + LinCompoundTag worldeditMeta = metadataTag.findTag("WorldEdit", LinTagType.compoundTag()); + if (worldeditMeta != null) { + origin = ReaderUtil.decodeBlockVector3(worldeditMeta.findTag("Origin", LinTagType.intArrayTag())); + } + } + BlockVector3 min = offset.add(origin); + + BlockArrayClipboard clipboard = new BlockArrayClipboard(new CuboidRegion( + min, + min.add(width, height, length).subtract(BlockVector3.ONE) + )); + clipboard.setOrigin(origin); + + decodeBlocksIntoClipboard(fixer, schematicTag, clipboard); + + LinCompoundTag biomeContainer = schematicTag.findTag("Biomes", LinTagType.compoundTag()); + if (biomeContainer != null) { + readBiomes3(clipboard, biomeContainer, fixer); + } + + LinListTag entities = schematicTag.findListTag("Entities", LinTagType.compoundTag()); + if (entities != null) { + ReaderUtil.readEntities(clipboard, entities.value(), fixer, true); + } + + return clipboard; + } + + private void decodeBlocksIntoClipboard( + VersionedDataFixer fixer, LinCompoundTag schematic, BlockArrayClipboard clipboard + ) throws IOException { + LinCompoundTag blockContainer = schematic.getTag("Blocks", LinTagType.compoundTag()); + + LinCompoundTag paletteObject = blockContainer.getTag("Palette", LinTagType.compoundTag()); + Map palette = ReaderUtil.decodePalette(paletteObject, fixer); + + byte[] blocks = blockContainer.getTag("Data", LinTagType.byteArrayTag()).value(); + LinListTag blockEntities = blockContainer.findListTag("BlockEntities", LinTagType.compoundTag()); + + ReaderUtil.initializeClipboardFromBlocks(clipboard, palette, blocks, blockEntities, fixer, true); + } + + private void readBiomes3( + BlockArrayClipboard clipboard, LinCompoundTag biomeContainer, VersionedDataFixer fixer + ) throws IOException { + LinCompoundTag paletteTag = biomeContainer.getTag("Palette", LinTagType.compoundTag()); + + Int2ObjectMap palette = ReaderUtil.readBiomePalette(fixer, paletteTag, LOGGER); + + int width = clipboard.getRegion().getWidth(); + int length = clipboard.getRegion().getLength(); + + byte[] biomes = biomeContainer.getTag("Data", LinTagType.byteArrayTag()).value(); + BlockVector3 min = clipboard.getMinimumPoint(); + int index = 0; + for (VarIntIterator iter = new VarIntIterator(biomes); iter.hasNext(); index++) { + int nextBiomeId = iter.nextInt(); + BiomeType type = palette.get(nextBiomeId); + BlockVector3 pos = ReaderUtil.decodePositionFromDataIndex(width, length, index); + clipboard.setBiome(min.add(pos), type); + } + } + + @Override + public void close() throws IOException { + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Writer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Writer.java new file mode 100644 index 000000000..4030c2f90 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Writer.java @@ -0,0 +1,233 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.block.BaseBlock; +import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntMaps; +import org.enginehub.linbus.stream.LinBinaryIO; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinRootEntry; +import org.enginehub.linbus.tree.LinTagType; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.function.Function; + +/** + * Writes schematic files using the Sponge Schematic Specification (Version 3). + */ +public class SpongeSchematicV3Writer implements ClipboardWriter { + + private static final int CURRENT_VERSION = 3; + + private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE; + private final DataOutputStream outputStream; + + public SpongeSchematicV3Writer(DataOutputStream outputStream) { + this.outputStream = outputStream; + } + + @Override + public void write(Clipboard clipboard) throws IOException { + //FAWE start - ensure clipboard is flushed in case of using clipboard-on-disk. Maintains allowing of the same code + // between upstream and FAWE + clipboard.flush(); + //FAWE end + LinBinaryIO.write(outputStream, + new LinRootEntry("", LinCompoundTag.builder().put("Schematic", write3(clipboard)).build()) + ); + } + + /** + * Writes a version 3 schematic file. + * + * @param clipboard The clipboard + * @return The schematic map + */ + private LinCompoundTag write3(Clipboard clipboard) { + Region region = clipboard.getRegion(); + BlockVector3 origin = clipboard.getOrigin(); + BlockVector3 min = region.getMinimumPoint(); + BlockVector3 offset = min.subtract(origin); + int width = region.getWidth(); + int height = region.getHeight(); + int length = region.getLength(); + + if (width > MAX_SIZE) { + throw new IllegalArgumentException("Width of region too large for a .schematic"); + } + if (height > MAX_SIZE) { + throw new IllegalArgumentException("Height of region too large for a .schematic"); + } + if (length > MAX_SIZE) { + throw new IllegalArgumentException("Length of region too large for a .schematic"); + } + + LinCompoundTag.Builder schematic = LinCompoundTag.builder(); + schematic.putInt("Version", CURRENT_VERSION); + schematic.putInt("DataVersion", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion() + ); + + LinCompoundTag.Builder metadata = LinCompoundTag.builder(); + metadata.putLong("Date", System.currentTimeMillis()); + + LinCompoundTag.Builder worldEditSection = LinCompoundTag.builder(); + worldEditSection.putString("Version", WorldEdit.getVersion()); + worldEditSection.putString("EditingPlatform", + WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).id() + ); + worldEditSection.putIntArray("Origin", new int[]{origin.x(), origin.y(), origin.z()}); + + LinCompoundTag.Builder platformsSection = LinCompoundTag.builder(); + for (Platform platform : WorldEdit.getInstance().getPlatformManager().getPlatforms()) { + platformsSection.put(platform.id(), LinCompoundTag + .builder() + .putString("Name", platform.getPlatformName()) + .putString("Version", platform.getPlatformVersion()) + .build()); + } + worldEditSection.put("Platforms", platformsSection.build()); + + metadata.put("WorldEdit", worldEditSection.build()); + + schematic.put("Metadata", metadata.build()); + + schematic.putShort("Width", (short) width); + schematic.putShort("Height", (short) height); + schematic.putShort("Length", (short) length); + + schematic.putIntArray("Offset", new int[]{offset.x(), offset.y(), offset.z(),}); + + schematic.put("Blocks", encodeBlocks(clipboard)); + + if (clipboard.hasBiomes()) { + schematic.put("Biomes", encodeBiomes(clipboard)); + } + + if (!clipboard.getEntities().isEmpty()) { + LinListTag value = WriterUtil.encodeEntities(clipboard, true); + if (value != null) { + schematic.put("Entities", value); + } + } + + return schematic.build(); + } + + private static final class PaletteMap { + + private final Object2IntMap contents = new Object2IntLinkedOpenHashMap<>(); + private int nextId = 0; + + public int getId(String key) { + int result = contents.getOrDefault(key, -1); + if (result != -1) { + return result; + } + int newValue = nextId; + nextId++; + contents.put(key, newValue); + return newValue; + } + + public LinCompoundTag toNbt() { + LinCompoundTag.Builder result = LinCompoundTag.builder(); + Object2IntMaps.fastForEach(contents, e -> result.putInt(e.getKey(), e.getIntValue())); + return result.build(); + } + + } + + private LinCompoundTag encodeBlocks(Clipboard clipboard) { + LinListTag.Builder blockEntities = LinListTag.builder(LinTagType.compoundTag()); + LinCompoundTag.Builder result = encodePalettedData(clipboard, point -> { + BaseBlock block = clipboard.getFullBlock(point); + // Also compute block entity side-effect here + LinCompoundTag nbt = block.getNbt(); + if (nbt != null) { + LinCompoundTag.Builder builder = LinCompoundTag.builder(); + + builder.putString("Id", block.getNbtId()); + BlockVector3 adjustedPos = point.subtract(clipboard.getMinimumPoint()); + builder.putIntArray("Pos", new int[]{adjustedPos.x(), adjustedPos.y(), adjustedPos.z()}); + builder.put("Data", nbt); + + blockEntities.add(builder.build()); + } + return block.toImmutableState().getAsString(); + }); + + return result.put("BlockEntities", blockEntities.build()).build(); + } + + private LinCompoundTag encodeBiomes(Clipboard clipboard) { + return encodePalettedData(clipboard, point -> clipboard.getBiome(point).id()).build(); + } + + private LinCompoundTag.Builder encodePalettedData( + Clipboard clipboard, Function keyFunction + ) { + BlockVector3 min = clipboard.getMinimumPoint(); + int width = clipboard.getRegion().getWidth(); + int height = clipboard.getRegion().getHeight(); + int length = clipboard.getRegion().getLength(); + + PaletteMap paletteMap = new PaletteMap(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length); + + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++) { + BlockVector3 point = min.add(x, y, z); + + String key = keyFunction.apply(point); + int id = paletteMap.getId(key); + + while ((id & -128) != 0) { + buffer.write(id & 127 | 128); + id >>>= 7; + } + buffer.write(id); + } + } + } + + return LinCompoundTag.builder().put("Palette", paletteMap.toNbt()).putByteArray("Data", buffer.toByteArray()); + } + + @Override + public void close() throws IOException { + outputStream.close(); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/VersionedDataFixer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/VersionedDataFixer.java new file mode 100644 index 000000000..35f6d58bc --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/VersionedDataFixer.java @@ -0,0 +1,47 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + + +import com.sk89q.worldedit.world.DataFixer; + +import javax.annotation.Nullable; + +public final class VersionedDataFixer { //FAWE - public + private final int dataVersion; + @Nullable + private final DataFixer fixer; + + public VersionedDataFixer(int dataVersion, @Nullable DataFixer fixer) { //FAWE - public + this.dataVersion = dataVersion; + this.fixer = fixer; + } + + public boolean isActive() { + return fixer != null; + } + + public T fixUp(DataFixer.FixType type, T original) { + if (!isActive()) { + return original; + } + return fixer.fixUp(type, original, dataVersion); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/WriterUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/WriterUtil.java new file mode 100644 index 000000000..17ff5004d --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/WriterUtil.java @@ -0,0 +1,91 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.sponge; + +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.util.Location; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; + +class WriterUtil { + + static LinListTag encodeEntities(Clipboard clipboard, boolean positionIsRelative) { + LinListTag.Builder entities = LinListTag.builder(LinTagType.compoundTag()); + for (Entity entity : clipboard.getEntities()) { + LinCompoundTag encoded = encodeEntity(clipboard, positionIsRelative, entity); + if (encoded != null) { + entities.add(encoded); + } + } + var result = entities.build(); + if (result.value().isEmpty()) { + return null; + } + return result; + } + + private static LinCompoundTag encodeEntity(Clipboard clipboard, boolean positionIsRelative, Entity e) { + BaseEntity state = e.getState(); + if (state == null) { + return null; + } + LinCompoundTag.Builder fullTagBuilder = LinCompoundTag.builder(); + LinCompoundTag.Builder dataTagBuilder = LinCompoundTag.builder(); + LinCompoundTag rawData = state.getNbt(); + if (rawData != null) { + dataTagBuilder.putAll(rawData.value()); + dataTagBuilder.remove("id"); + } + final Location location = e.getLocation(); + Vector3 pos = location.toVector(); + dataTagBuilder.put("Rotation", encodeRotation(location)); + if (positionIsRelative) { + pos = pos.subtract(clipboard.getMinimumPoint().toVector3()); + + fullTagBuilder.put("Data", dataTagBuilder.build()); + } else { + fullTagBuilder.putAll(dataTagBuilder.build().value()); + } + fullTagBuilder.putString("Id", state.getType().id()); + fullTagBuilder.put("Pos", encodeVector(pos)); + + return fullTagBuilder.build(); + } + + static LinListTag encodeVector(Vector3 vector) { + return LinListTag.builder(LinTagType.doubleTag()).add(LinDoubleTag.of(vector.x())).add(LinDoubleTag.of(vector.y())).add( + LinDoubleTag.of(vector.z())).build(); + } + + static LinListTag encodeRotation(Location location) { + return LinListTag + .builder(LinTagType.floatTag()) + .add(LinFloatTag.of(location.getYaw())) + .add(LinFloatTag.of(location.getPitch())) + .build(); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/package-info.java new file mode 100644 index 000000000..930ae5efb --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/package-info.java @@ -0,0 +1,26 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * This package is internal, containing implementation details of the Sponge Schematic + * Specification. Use the {@link com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats} or + * {@link com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat} classes to + * acquire readers and writers instead. + */ +package com.sk89q.worldedit.extent.clipboard.io.sponge; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java index ff516e4c9..18e69c7a0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java @@ -104,7 +104,7 @@ public class BlockBagExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 position, B block) throws WorldEditException { - return setBlock(position.getX(), position.getY(), position.getZ(), block); + return setBlock(position.x(), position.y(), position.z(), block); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java index 55340bb07..237c0b220 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java @@ -86,6 +86,11 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde priorityMap.put(BlockTypes.WHITE_BED, PlacementPriority.LAST); priorityMap.put(BlockTypes.YELLOW_BED, PlacementPriority.LAST); priorityMap.put(BlockTypes.GRASS, PlacementPriority.LAST); + // Keep "grass" for <1.20.3 compat + @SuppressWarnings("deprecation") + BlockType grass = BlockTypes.GRASS; + priorityMap.put(grass, PlacementPriority.LAST); + priorityMap.put(BlockTypes.SHORT_GRASS, PlacementPriority.LAST); priorityMap.put(BlockTypes.TALL_GRASS, PlacementPriority.LAST); priorityMap.put(BlockTypes.ROSE_BUSH, PlacementPriority.LAST); priorityMap.put(BlockTypes.DANDELION, PlacementPriority.LAST); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index f22d7036d..519463760 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -391,9 +391,9 @@ public class BlockTransformExtent extends ResettableExtent { if (direction != null) { Vector3 applyAbsolute = transform.apply(direction.toVector()); Vector3 applyOrigin = transform.apply(Vector3.ZERO); - applyAbsolute.mutX(applyAbsolute.getX() - applyOrigin.getX()); - applyAbsolute.mutY(applyAbsolute.getY() - applyOrigin.getY()); - applyAbsolute.mutZ(applyAbsolute.getZ() - applyOrigin.getZ()); + applyAbsolute.mutX(applyAbsolute.x() - applyOrigin.x()); + applyAbsolute.mutY(applyAbsolute.y() - applyOrigin.y()); + applyAbsolute.mutZ(applyAbsolute.z() - applyOrigin.z()); Direction newDirection = Direction.findClosest( applyAbsolute, @@ -401,7 +401,7 @@ public class BlockTransformExtent extends ResettableExtent { ); if (newDirection != null) { - Map values = new HashMap<>(tag.getValue()); + Map> values = new HashMap<>(tag.getValue()); values.put("Rot", new ByteTag((byte) MCDirections.toRotation(newDirection))); tag = new CompoundTag(values); } @@ -441,7 +441,7 @@ public class BlockTransformExtent extends ResettableExtent { if (Settings.settings().ENABLED_COMPONENTS.DEBUG) { LOGGER.warn(String.format( "Index outside direction array length found for block:{%s} property:{%s}", - state.getBlockType().getId(), + state.getBlockType().id(), property.getName() )); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java index 498e5ce9f..38b79dc34 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java @@ -62,6 +62,7 @@ public class BlockChangeLimiter extends AbstractDelegateExtent { * * @param limit the limit (>= 0) or -1 for no limit */ + @SuppressWarnings("this-escape") // Unlikely anyone is extending this in practice public void setLimit(int limit) { checkArgument(limit >= -1, "limit >= -1 required"); this.limit = limit; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/DataValidatorExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/DataValidatorExtent.java index 1b806c7d8..1161779d9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/DataValidatorExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/DataValidatorExtent.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; @@ -34,7 +35,8 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class DataValidatorExtent extends AbstractDelegateExtent { - private final World world; + private final int minY; + private final int maxY; /** * Create a new instance. @@ -43,16 +45,27 @@ public class DataValidatorExtent extends AbstractDelegateExtent { * @param world the world */ public DataValidatorExtent(Extent extent, World world) { + this(extent, checkNotNull(world).getMinY(), world.getMaxY()); + } + + /** + * Create a new instance. + * + * @param extent The extent + * @param minY The minimum Y height to allow (inclusive) + * @param maxY The maximum Y height to allow (inclusive) + */ + public DataValidatorExtent(Extent extent, int minY, int maxY) { super(extent); - checkNotNull(world); - this.world = world; + this.minY = minY; + this.maxY = maxY; } @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { - final int y = location.getBlockY(); + final int y = location.y(); final BlockType type = block.getBlockType(); - if (y < world.getMinY() || y > world.getMaxY()) { + if (y < minY || y > maxY) { return false; } @@ -64,4 +77,15 @@ public class DataValidatorExtent extends AbstractDelegateExtent { return super.setBlock(location, block); } + @Override + public boolean setBiome(BlockVector3 location, BiomeType biome) { + final int y = location.y(); + + if (y < minY || y > maxY) { + return false; + } + + return super.setBiome(location, biome); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java index 5a90aebbb..413bd31bf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java @@ -88,7 +88,7 @@ public class SideEffectExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.DELAYED) { - dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4)); + dirtyChunks.add(BlockVector2.at(location.x() >> 4, location.z() >> 4)); } if (postEditSimulation) { positions.put(location, world.getBlock(location)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java index 88cf4fc6f..b2670113a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java @@ -26,9 +26,9 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.Collection; @@ -115,9 +115,7 @@ public class SurvivalModeExtent extends AbstractDelegateExtent { } else { // Can't be an inlined check due to inconsistent generic return type if (stripNbt) { - //FAWE start - Use CompoundBinaryTag - return super.setBlock(location, block.toBaseBlock((CompoundBinaryTag) null)); - //FAWE end + return super.setBlock(location, block.toBaseBlock((LinCompoundTag) null)); } else { return super.setBlock(location, block); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/BiomeReplace.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/BiomeReplace.java index 6ae4ad2ec..90d7f31cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/BiomeReplace.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/BiomeReplace.java @@ -70,7 +70,7 @@ public class BiomeReplace implements FlatRegionFunction, RegionFunction { @Deprecated public boolean apply(BlockVector2 position) throws WorldEditException { boolean success = false; - for (int y = extent.getMinimumPoint().getY(); y <= extent.getMaximumPoint().getY(); y++) { + for (int y = extent.getMinimumPoint().y(); y <= extent.getMaximumPoint().y(); y++) { success |= apply(position.toBlockVector3(y)); } return success; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/ExtentBiomeCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/ExtentBiomeCopy.java index 076c1f561..5643da36a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/ExtentBiomeCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/biome/ExtentBiomeCopy.java @@ -102,7 +102,7 @@ public class ExtentBiomeCopy implements FlatRegionFunction, RegionFunction { @Deprecated public boolean apply(BlockVector2 position) throws WorldEditException { boolean success = false; - for (int y = destination.getMinimumPoint().getY(); y <= destination.getMaximumPoint().getY(); y++) { + for (int y = destination.getMinimumPoint().y(); y <= destination.getMaximumPoint().y(); y++) { success |= apply(position.toBlockVector3(y)); } return success; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java index 093a7737f..e4b390797 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java @@ -28,10 +28,9 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction.Flag; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.NumberBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTag; import static com.google.common.base.Preconditions.checkNotNull; @@ -88,14 +87,13 @@ public class ExtentBlockCopy implements RegionFunction { * @return a new state or the existing one */ private BaseBlock transformNbtData(BaseBlock state) { - //FAWE start - Replace CompoundTag with CompoundBinaryTag - CompoundBinaryTag tag = state.getNbt(); + LinCompoundTag tag = state.getNbt(); if (tag != null) { // Handle blocks which store their rotation in NBT - BinaryTag rotTag = tag.get("Rot"); - if (rotTag instanceof NumberBinaryTag) { - int rot = ((NumberBinaryTag) rotTag).intValue(); + LinTag rotTag = tag.value().get("Rot"); + if (rotTag.value() instanceof Number number) { + int rot = number.intValue(); Direction direction = MCDirections.fromRotation(rot); @@ -105,8 +103,9 @@ public class ExtentBlockCopy implements RegionFunction { if (newDirection != null) { return state.toBaseBlock( - tag.putByte("Rot", (byte) MCDirections.toRotation(newDirection)) - //FAWE end + tag.toBuilder() + .putByte("Rot", (byte) MCDirections.toRotation(newDirection)) + .build() ); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java index c84fcc67a..e64bb69bb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java @@ -26,11 +26,12 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.BooleanProperty; import com.sk89q.worldedit.registry.state.EnumProperty; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.Locale; -import java.util.Map; public class SnowSimulator implements LayerFunction { @@ -105,7 +106,7 @@ public class SnowSimulator implements LayerFunction { // Can't put snow this far up - if (position.getBlockY() == this.extent.getMaximumPoint().getBlockY()) { + if (position.y() == this.extent.getMaximumPoint().y()) { return false; } @@ -116,26 +117,23 @@ public class SnowSimulator implements LayerFunction { if (!above.getBlockType().getMaterial().isAir() && (!stack || above.getBlockType() != BlockTypes.SNOW)) { return false; //FAWE start - } else if (!block.getBlockType().getId().toLowerCase(Locale.ROOT).contains("ice") && this.extent.getEmittedLight( + } else if (!block.getBlockType().id().toLowerCase(Locale.ROOT).contains("ice") && this.extent.getEmittedLight( abovePosition) > 10) { return false; } else if (!block.getBlockType().getMaterial().isFullCube()) { - Map, Object> states = block.getStates(); - if (states.containsKey(slab) && block.getState(slab).equalsIgnoreCase("bottom")) { + BlockType type = block.getBlockType(); + if (type.hasProperty(slab) && block.getState(slab).equalsIgnoreCase("bottom")) { return false; - } else if (states.containsKey(trapdoorOpen) && states.containsKey(trapdoor) && (block.getState(trapdoorOpen) - || block.getState(trapdoor).equalsIgnoreCase("bottom"))) { + } else if ((type.hasProperty(trapdoorOpen) && block.getState(trapdoorOpen)) || + (type.hasProperty(trapdoor) && block.getState(trapdoor).equalsIgnoreCase("bottom"))) { return false; - } else if (states.containsKey(stair) && block.getState(stair).equalsIgnoreCase("bottom")) { + } else if (type.hasProperty(stair) && block.getState(stair).equalsIgnoreCase("bottom")) { return false; } else { return false; } //FAWE end - } else if (!block.getBlockType().getId().toLowerCase(Locale.ROOT).contains("ice") && block - .getBlockType() - .getMaterial() - .isTranslucent()) { + } else if (!BlockCategories.SNOW_LAYER_CAN_SURVIVE_ON.contains(block.getBlockType())) { return false; } @@ -144,14 +142,14 @@ public class SnowSimulator implements LayerFunction { // We've hit the highest layer (If it doesn't contain current + 2 it means it's 1 away from full) if (!snowLayersProperty.getValues().contains(currentHeight + 2)) { if (this.extent.setBlock(abovePosition, snowBlock)) { - if (block.getStates().containsKey(snowy)) { + if (block.getBlockType().hasProperty(snowy)) { this.extent.setBlock(position, block.with(snowy, true)); } this.affected++; } } else { if (this.extent.setBlock(abovePosition, above.with(snowLayersProperty, currentHeight + 1))) { - if (block.getStates().containsKey(snowy)) { + if (block.getBlockType().hasProperty(snowy)) { this.extent.setBlock(position, block.with(snowy, true)); } this.affected++; @@ -160,7 +158,7 @@ public class SnowSimulator implements LayerFunction { return false; } if (this.extent.setBlock(abovePosition, snow)) { - if (block.getStates().containsKey(snowy)) { + if (block.getBlockType().hasProperty(snowy)) { this.extent.setBlock(position, block.with(snowy, true)); } this.affected++; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java index 7a034d7bd..149464bef 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java @@ -206,9 +206,9 @@ public class ExtentEntityCopy implements EntityFunction { BlockVector3 newLeash = transform.apply(tilePosition.subtract(from)).add(to).toBlockPoint(); return new BaseEntity(state.getType(), tag.createBuilder() .put("Leash", leashCompound.createBuilder() - .putInt("X", newLeash.getBlockX()) - .putInt("Y", newLeash.getBlockY()) - .putInt("Z", newLeash.getBlockZ()) + .putInt("X", newLeash.x()) + .putInt("Y", newLeash.y()) + .putInt("Z", newLeash.z()) .build() ).build()); } @@ -226,9 +226,9 @@ public class ExtentEntityCopy implements EntityFunction { BlockVector3 newTilePosition = transform.apply(tilePosition.subtract(from)).add(to).toBlockPoint(); CompoundTagBuilder builder = tag.createBuilder() - .putInt("TileX", newTilePosition.getBlockX()) - .putInt("TileY", newTilePosition.getBlockY()) - .putInt("TileZ", newTilePosition.getBlockZ()); + .putInt("TileX", newTilePosition.x()) + .putInt("TileY", newTilePosition.y()) + .putInt("TileZ", newTilePosition.z()); if (hasFacing) { boolean isPainting = state.getType() == EntityTypes.PAINTING; // Paintings have different facing values @@ -257,7 +257,8 @@ public class ExtentEntityCopy implements EntityFunction { //FAWE start if (hasRotation) { ListTag orgrot = state.getNbtData().getListTag("Rotation"); - Vector3 orgDirection = new Location(source, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); + // source extent may be null: use non-nullable destination instead since this is just a conversion into a vector. + Vector3 orgDirection = new Location(destination, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); Vector3 newDirection = transform.apply(orgDirection).subtract(transform.apply(Vector3.ZERO)).normalize(); builder.put( "Rotation", @@ -276,7 +277,8 @@ public class ExtentEntityCopy implements EntityFunction { CompoundTagBuilder builder = tag.createBuilder(); ListTag orgrot = state.getNbtData().getListTag("Rotation"); - Vector3 orgDirection = new Location(source, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); + // source extent may be null: use non-nullable destination instead since this is just a conversion into a vector. + Vector3 orgDirection = new Location(destination, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); Vector3 newDirection = transform.apply(orgDirection).subtract(transform.apply(Vector3.ZERO)).normalize(); builder.put( "Rotation", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/ApplyLayer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/ApplyLayer.java index 88e3218c0..c7ecc1207 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/ApplyLayer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/ApplyLayer.java @@ -53,8 +53,8 @@ public class ApplyLayer implements Contextual { return new LayerVisitor( localRegion, - localRegion.getMinimumPoint().getY(), - localRegion.getMaximumPoint().getY(), + localRegion.getMinimumPoint().y(), + localRegion.getMaximumPoint().y(), function.createFromContext(context), //FAWE start - provide extent for preloading context.getDestination() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java index 115c05044..6dea78892 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java @@ -141,13 +141,13 @@ public class Deform implements Contextual { zero = max.add(min).multiply(0.5); unit = max.subtract(zero); - if (unit.getX() == 0) { + if (unit.x() == 0) { unit = unit.withX(1.0); } - if (unit.getY() == 0) { + if (unit.y() == 0) { unit = unit.withY(1.0); } - if (unit.getZ() == 0) { + if (unit.z() == 0) { unit = unit.withZ(1.0); } break; @@ -167,24 +167,14 @@ public class Deform implements Contextual { ); } - private static final class DeformOperation implements Operation { - - private final Extent destination; - private final Region region; - private final Vector3 zero; - private final Vector3 unit; - private final String expression; - private final int timeout; - - private DeformOperation(Extent destination, Region region, Vector3 zero, Vector3 unit, String expression, int timeout) { - this.destination = destination; - this.region = region; - this.zero = zero; - this.unit = unit; - this.expression = expression; - this.timeout = timeout; - } - + private record DeformOperation( + Extent destination, + Region region, + Vector3 zero, + Vector3 unit, + String expression, //FAWE: Expression -> String + int timeout + ) implements Operation { @Override public Operation resume(RunContext run) throws WorldEditException { try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java index 5ea9aa66e..a1ddb2240 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; /** @@ -103,7 +104,12 @@ public class FloraGenerator implements RegionFunction { */ public static Pattern getTemperatePattern() { RandomPattern pattern = new RandomPattern(); - pattern.add(BlockTypes.GRASS.getDefaultState(), 300); + BlockType grass = BlockTypes.SHORT_GRASS; + if (grass == null) { + // Fallback for <1.20.3 compat + grass = BlockTypes.GRASS; + } + pattern.add(grass.getDefaultState(), 300); pattern.add(BlockTypes.POPPY.getDefaultState(), 5); pattern.add(BlockTypes.DANDELION.getDefaultState(), 5); return pattern; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java index cd3ef56d5..ab919b35f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java @@ -94,7 +94,7 @@ public class BiomeMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - BiomeType biome = getExtent().getBiome(vector); + BiomeType biome = vector.getBiome(getExtent()); return biomes.contains(biome); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java index bad9781ea..a1b869efb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java @@ -46,7 +46,7 @@ public class BlockCategoryMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return category.contains(getExtent().getBlock(vector)); + return category.contains(vector.getBlock(getExtent())); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index 9f191a4cc..c7d3473f3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -204,7 +204,7 @@ public class BlockMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); return ordinals[test] || replacesAir() && test == 0; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java index ac558520c..0c563cdf7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java @@ -56,7 +56,7 @@ public class BlockStateMask extends AbstractExtentMask { //FAWE start @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector)); + return test(vector.getBlock(getExtent())); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java index 17f1419e5..c3567b6d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java @@ -124,7 +124,7 @@ public class BlockTypeMask extends AbstractExtentMask { //FAWE start @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector).getBlockType()); + return test(vector.getBlock(getExtent()).getBlockType()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BoundedHeightMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BoundedHeightMask.java index 301f2104c..808465416 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BoundedHeightMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BoundedHeightMask.java @@ -41,14 +41,14 @@ public class BoundedHeightMask extends AbstractMask { * @param maxY the maximum Y (must be equal to or greater than minY) */ public BoundedHeightMask(int minY, int maxY) { - checkArgument(minY <= maxY, "minY <= maxY required"); + checkArgument(minY <= maxY, "minY <= maxY required. minY:" + minY + " and maxY:" + maxY + " were given."); this.minY = minY; this.maxY = maxY; } @Override public boolean test(BlockVector3 vector) { - return vector.getY() >= minY && vector.getY() <= maxY; + return vector.y() >= minY && vector.y() <= maxY; } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java index b75a4cd1e..be62c2eae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java @@ -41,7 +41,7 @@ public class ExistingBlockMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return !getExtent().getBlock(vector).getBlockType().getMaterial().isAir(); + return !vector.getBlock(getExtent()).getBlockType().getMaterial().isAir(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java index 1b95057ba..e5647332e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java @@ -73,10 +73,10 @@ public class ExpressionMask extends AbstractMask { ((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector.toVector3()); } if (timeout == null) { - return expression.evaluate(vector.getX(), vector.getY(), vector.getZ()) > 0; + return expression.evaluate(vector.x(), vector.y(), vector.z()) > 0; } else { return expression.evaluate( - new double[]{vector.getX(), vector.getY(), vector.getZ()}, + new double[]{vector.x(), vector.y(), vector.z()}, timeout.getAsInt() ) > 0; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java index 0d2854b7c..7d5e22e99 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java @@ -63,9 +63,9 @@ public class ExpressionMask2D extends AbstractMask2D { public boolean test(BlockVector2 vector) { try { if (timeout == null) { - return expression.evaluate(vector.getX(), 0, vector.getZ()) > 0; + return expression.evaluate(vector.x(), 0, vector.z()) > 0; } else { - return expression.evaluate(timeout.getAsInt(), vector.getX(), 0, vector.getZ()) > 0; + return expression.evaluate(timeout.getAsInt(), vector.x(), 0, vector.z()) > 0; } } catch (EvaluationException e) { return false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java index e8b14b95a..6bb39b958 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java @@ -29,7 +29,7 @@ public class InverseSingleBlockStateMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); if (isAir && test == 0) { return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java index 3c4cb1378..85e85a8c2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -22,7 +22,11 @@ package com.sk89q.worldedit.function.mask; import com.fastasyncworldedit.core.extent.filter.MaskFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.function.mask.InverseMask; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import javax.annotation.Nullable; @@ -64,7 +68,21 @@ public interface Mask { return null; } + @SuppressWarnings({"unchecked", "rawtypes"}) default MaskFilter toFilter(T filter) { + final VectorizedMask mask = SimdSupport.vectorizedTargetMask(this); + if (mask != null) { + VectorizedFilter vectorizedFilter = null; + if (filter instanceof VectorizedFilter vf) { + vectorizedFilter = vf; + } else if (filter instanceof Pattern p) { + vectorizedFilter = SimdSupport.vectorizedPattern(p); + } + if (vectorizedFilter != null) { + // also pass original? + return new MaskFilter.VectorizedMaskFilter(vectorizedFilter, this); + } + } return new MaskFilter<>(filter, this); } @@ -87,7 +105,7 @@ public interface Mask { } else if (this instanceof Masks.AlwaysFalse) { return Masks.ALWAYS_TRUE; } else if (this instanceof Masks.NegatedMask) { - return ((Masks.NegatedMask) this).mask; + return ((Masks.NegatedMask) this).mask(); } return new InverseMask(this); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion.java similarity index 91% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion.java index 381754a3c..e35ac319d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion.java @@ -1,9 +1,5 @@ -package com.fastasyncworldedit.core.function.mask; +package com.sk89q.worldedit.function.mask; -import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.mask.Mask2D; -import com.sk89q.worldedit.function.mask.MaskIntersection; -import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.math.BlockVector3; import javax.annotation.Nullable; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion2D.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion2D.java similarity index 86% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion2D.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion2D.java index 53edf2c45..a7995a9cf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/MaskUnion2D.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskUnion2D.java @@ -1,7 +1,5 @@ -package com.fastasyncworldedit.core.function.mask; +package com.sk89q.worldedit.function.mask; -import com.sk89q.worldedit.function.mask.Mask2D; -import com.sk89q.worldedit.function.mask.MaskIntersection2D; import com.sk89q.worldedit.math.BlockVector2; import java.util.Collection; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Masks.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Masks.java index d3cb4cad7..478d2732a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Masks.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Masks.java @@ -211,15 +211,7 @@ public final class Masks { } - //FAWE start - protected > private - protected static class NegatedMask implements Mask { - - //FAWE end - protected final Mask mask; - - private NegatedMask(Mask mask) { - this.mask = mask; - } + protected record NegatedMask(Mask mask) implements Mask { @Override public boolean test(BlockVector3 vector) { @@ -245,13 +237,7 @@ public final class Masks { } - private static class NegatedMask2D implements Mask2D { - - private final Mask2D mask; - - private NegatedMask2D(Mask2D mask) { - this.mask = mask; - } + private record NegatedMask2D(Mask2D mask) implements Mask2D { @Override public boolean test(BlockVector2 vector) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/NoiseFilter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/NoiseFilter.java index 684148505..8dd9c26d9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/NoiseFilter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/NoiseFilter.java @@ -97,7 +97,7 @@ public class NoiseFilter extends AbstractMask { @Override public boolean test(BlockVector3 vector) { //FAWE start - mutable - return noiseGenerator.noise(mutable.setComponents(vector.getX(), vector.getZ(), vector.getZ())) <= density; + return noiseGenerator.noise(mutable.setComponents(vector.x(), vector.y(), vector.z())) <= density; //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java index 2c809ada4..39eda315b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java @@ -116,7 +116,7 @@ public class OffsetMask extends AbstractMask { public boolean test(BlockVector3 vector) { //FAWE start - ignore resultant position outside world height range BlockVector3 testPos = vector.add(offset); - if (testPos.getBlockY() < minY || testPos.getBlockY() > maxY) { + if (testPos.y() < minY || testPos.y() > maxY) { return false; } return getMask().test(testPos); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask2D.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask2D.java index 3e70c9ddd..f08811513 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask2D.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask2D.java @@ -89,13 +89,13 @@ public class OffsetMask2D extends AbstractMask2D { //FAWE start @Override public boolean test(BlockVector2 vector) { - mutableBlockVector2.setComponents(vector.getX() + offset.getX(), vector.getZ() + offset.getZ()); + mutableBlockVector2.setComponents(vector.x() + offset.x(), vector.z() + offset.z()); return getMask().test(mutableBlockVector2); } @Override public Mask2D copy2D() { - return new OffsetMask2D(mask.copy2D(), BlockVector2.at(offset.getX(), offset.getZ())); + return new OffsetMask2D(mask.copy2D(), BlockVector2.at(offset.x(), offset.z())); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/BackwardsExtentBlockCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/BackwardsExtentBlockCopy.java index f766cf8d7..75018d96d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/BackwardsExtentBlockCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/BackwardsExtentBlockCopy.java @@ -52,9 +52,9 @@ public class BackwardsExtentBlockCopy extends RegionVisitor implements Operation BlockVector3 max = BlockVector3.at(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); BlockVector3 pos1 = region.getMinimumPoint(); BlockVector3 pos2 = region.getMaximumPoint(); - for (int x : new int[]{pos1.getBlockX(), pos2.getBlockX()}) { - for (int y : new int[]{pos1.getBlockY(), pos2.getBlockY()}) { - for (int z : new int[]{pos1.getBlockZ(), pos2.getBlockZ()}) { + for (int x : new int[]{pos1.x(), pos2.x()}) { + for (int y : new int[]{pos1.y(), pos2.y()}) { + for (int z : new int[]{pos1.z(), pos2.z()}) { BlockVector3 pt = transform(transform, BlockVector3.at(x, y, z)); min = min.getMinimum(pt); max = max.getMaximum(pt); @@ -65,13 +65,13 @@ public class BackwardsExtentBlockCopy extends RegionVisitor implements Operation } private BlockVector3 transform(Transform transform, BlockVector3 pt) { - mutV3.mutX(((pt.getBlockX() - origin.getBlockX()))); - mutV3.mutY(((pt.getBlockY() - origin.getBlockY()))); - mutV3.mutZ(((pt.getBlockZ() - origin.getBlockZ()))); + mutV3.mutX(((pt.x() - origin.x()))); + mutV3.mutY(((pt.y() - origin.y()))); + mutV3.mutZ(((pt.z() - origin.z()))); Vector3 tmp = transform.apply(mutV3); - mutBV3.mutX((tmp.getBlockX() + origin.getBlockX())); - mutBV3.mutY((tmp.getBlockY() + origin.getBlockY())); - mutBV3.mutZ((tmp.getBlockZ() + origin.getBlockZ())); + mutBV3.mutX((tmp.getBlockX() + origin.x())); + mutBV3.mutY((tmp.getBlockY() + origin.y())); + mutBV3.mutZ((tmp.getBlockZ() + origin.z())); return mutBV3; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java index 12359fdee..ea52bf335 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.function.operation; +import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; +import com.fastasyncworldedit.core.history.changeset.ChangeExchangeCoordinator; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.UndoContext; @@ -56,6 +58,7 @@ public class ChangeSetExecutor implements Operation { //FAWE end private final Iterator iterator; + private final ChangeExchangeCoordinator changeExchangeCoordinator; private final Type type; private final UndoContext context; @@ -74,18 +77,42 @@ public class ChangeSetExecutor implements Operation { this.type = type; this.context = context; - if (changeSet instanceof AbstractChangeSet) { - iterator = ((AbstractChangeSet) changeSet).getIterator(blockBag, inventory, type == Type.REDO); + if (changeSet instanceof AbstractChangeSet abstractChangeSet) { + if (Settings.settings().EXPERIMENTAL.UNDO_BATCH_SIZE > 0) { + this.changeExchangeCoordinator = abstractChangeSet.getCoordinatedChanges(blockBag, inventory, type == Type.REDO); + this.iterator = null; + } else { + this.iterator = abstractChangeSet.getIterator(blockBag, inventory, type == Type.REDO); + this.changeExchangeCoordinator = null; + } } else if (type == Type.UNDO) { iterator = changeSet.backwardIterator(); + this.changeExchangeCoordinator = null; } else { iterator = changeSet.forwardIterator(); + this.changeExchangeCoordinator = null; } } //FAWE end @Override public Operation resume(RunContext run) throws WorldEditException { + // FAWE start - ChangeExchangeCoordinator + if (this.changeExchangeCoordinator != null) { + try (this.changeExchangeCoordinator) { + Change[] changes = new Change[Settings.settings().EXPERIMENTAL.UNDO_BATCH_SIZE]; + while ((changes = this.changeExchangeCoordinator.take(changes)) != null) { + for (final Change change : changes) { + if (change == null) { + return null; // end + } + type.perform(change, context); + } + } + return null; + } + } + // FAWE end while (iterator.hasNext()) { Change change = iterator.next(); //FAWE start - types > individual history step diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java index 9959c9d67..f98d5f924 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java @@ -306,9 +306,9 @@ public class ForwardExtentCopy implements Operation { if (!translation.equals(BlockVector3.ZERO)) { finalDest = new BlockTranslateExtent( finalDest, - translation.getBlockX(), - translation.getBlockY(), - translation.getBlockZ() + translation.x(), + translation.y(), + translation.z() ); } //FAWE end @@ -349,21 +349,21 @@ public class ForwardExtentCopy implements Operation { if (sourceFunction != null) { BlockVector3 disAbs = translation.abs(); BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); - boolean overlap = (disAbs.getBlockX() < size.getBlockX() && disAbs.getBlockY() < size.getBlockY() && disAbs.getBlockZ() < size - .getBlockZ()); + boolean overlap = (disAbs.x() < size.x() && disAbs.y() < size.y() && disAbs.z() < size + .z()); RegionFunction copySrcFunc = sourceFunction; if (overlap && translation.length() != 0) { - int x = translation.getBlockX(); - int y = translation.getBlockY(); - int z = translation.getBlockZ(); + int x = translation.x(); + int y = translation.y(); + int z = translation.z(); maskFunc = position -> { BlockVector3 bv = BlockVector3.at( - position.getBlockX() + x, - position.getBlockY() + y, - position.getBlockZ() + z + position.x() + x, + position.y() + y, + position.z() + z ); if (region.contains(bv)) { return sourceFunction.apply(bv); @@ -373,9 +373,9 @@ public class ForwardExtentCopy implements Operation { copySrcFunc = position -> { BlockVector3 bv = BlockVector3.at( - position.getBlockX() - x, - position.getBlockY() - y, - position.getBlockZ() - z + position.x() - x, + position.y() - y, + position.z() - z ); if (!region.contains(bv)) { return sourceFunction.apply(position); @@ -446,6 +446,10 @@ public class ForwardExtentCopy implements Operation { } affectedBlocks += blockCopy.getAffected(); + if (copyingBiomes) { + // We know biomes will have happened unless something else has gone wrong. Just calculate it. + affectedBiomeCols += source.fullySupports3DBiomes() ? (getAffected() >> 2) : (region.getWidth() * region.getLength()); + } //FAWE end return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/package-info.java index 5b9eb7485..13a3d4e7c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/package-info.java @@ -1,6 +1,6 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.function.operation.BackwardsExtentBlockCopy + * {@link com.sk89q.worldedit.function.operation.BackwardsExtentBlockCopy} */ package com.sk89q.worldedit.function.operation; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/ExtentBufferedCompositePattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/ExtentBufferedCompositePattern.java index 49e7f5472..863cf1e25 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/ExtentBufferedCompositePattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/ExtentBufferedCompositePattern.java @@ -25,6 +25,8 @@ import com.sk89q.worldedit.extent.buffer.ExtentBuffer; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; +import java.util.Arrays; + import static com.google.common.base.Preconditions.checkArgument; /** @@ -64,4 +66,12 @@ public class ExtentBufferedCompositePattern extends AbstractExtentPattern { return lastBlock; } + //FAWE - stateful pattern + @Override + public Pattern fork() { + final Pattern[] forkedPatterns = Arrays.stream(patterns).map(Pattern::fork).toArray(Pattern[]::new); + return new ExtentBufferedCompositePattern(getExtent(), forkedPatterns); + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java index 801b07a65..69563af87 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.block.BaseBlock; /** @@ -59,6 +60,11 @@ public interface Pattern extends Filter { apply(block, block, block); } + @Override + default Pattern fork() { // covariant return type + return this; + } + //FAWE end /** @@ -69,4 +75,14 @@ public interface Pattern extends Filter { */ BaseBlock applyBlock(BlockVector3 position); + /** + * Get the likely maximum size of the volume this pattern will affect + * + * @return Pattern size + * @since 2.9.2 + */ + default BlockVector3 size() { + return BlockVector3.ONE; + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java index 0568fd5b8..bc13fe4de 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java @@ -27,7 +27,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -41,7 +41,7 @@ public class RandomPattern extends AbstractPattern { //FAWE start - SimpleRandom > Random, LHS

> List private final SimpleRandom random; - private Map weights = new HashMap<>(); + private Map weights = new LinkedHashMap<>(); private RandomCollection collection; private LinkedHashSet patterns = new LinkedHashSet<>(); //FAWE end @@ -67,6 +67,13 @@ public class RandomPattern extends AbstractPattern { this.collection = RandomCollection.of(weights, random); this.patterns = parent.patterns; } + + private RandomPattern(SimpleRandom random, Map weights) { + this.random = random; + this.weights = weights; + this.collection = RandomCollection.of(weights, random); + this.patterns = new LinkedHashSet<>(weights.keySet()); + } //FAWE end /** @@ -100,13 +107,21 @@ public class RandomPattern extends AbstractPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { - return collection.next(position.getBlockX(), position.getBlockY(), position.getBlockZ()).applyBlock(position); + return collection.next(position.x(), position.y(), position.z()).applyBlock(position); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set); + return collection.next(get.x(), get.y(), get.z()).apply(extent, get, set); } + + @Override + public Pattern fork() { + final LinkedHashMap newWeights = new LinkedHashMap<>(); + this.weights.forEach((p, w) -> newWeights.put(p.fork(), w)); + return new RandomPattern(this.random, newWeights); + } + //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RepeatingExtentPattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RepeatingExtentPattern.java index 490c47cf2..ed62f92d8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RepeatingExtentPattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RepeatingExtentPattern.java @@ -88,9 +88,9 @@ public class RepeatingExtentPattern extends AbstractExtentPattern { @Override public BaseBlock applyBlock(BlockVector3 position) { //FAWE start - calculate offset - int x = Math.floorMod(position.getBlockX() + offset.getBlockX(), size.getBlockX()) + origin.getBlockX(); - int y = Math.floorMod(position.getBlockY() + offset.getBlockY(), size.getBlockY()) + origin.getBlockY(); - int z = Math.floorMod(position.getBlockZ() + offset.getBlockZ(), size.getBlockZ()) + origin.getBlockZ(); + int x = Math.floorMod(position.x() + offset.x(), size.x()) + origin.x(); + int y = Math.floorMod(position.y() + offset.y(), size.y()) + origin.y(); + int z = Math.floorMod(position.z() + offset.z(), size.z()) + origin.z(); //FAWE end return getExtent().getFullBlock(x, y, z); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/StateApplyingPattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/StateApplyingPattern.java index 3d834f76b..b328e78ea 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/StateApplyingPattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/StateApplyingPattern.java @@ -29,13 +29,16 @@ import com.sk89q.worldedit.world.block.BlockType; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import static com.sk89q.worldedit.blocks.Blocks.resolveProperties; public class StateApplyingPattern extends AbstractExtentPattern { private final Map states; - private final Map, Object>> cache = Maps.newHashMap(); + //FAWE - avoid race conditions + private final Map, Object>> cache = new ConcurrentHashMap<>(); + //FAWE end public StateApplyingPattern(Extent extent, Map statesToSet) { super(extent); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java index 7f3e5da63..796f02700 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java @@ -305,10 +305,10 @@ public abstract class BreadthFirstSearch implements Operation { if (loadCount > Settings.settings().QUEUE.PRELOAD_CHUNK_COUNT) { break outer; } - int x = from.getBlockX() + direction.getBlockX(); - int z = from.getBlockZ() + direction.getBlockX(); + int x = from.x() + direction.x(); + int z = from.z() + direction.x(); if (cx != (cx = x >> 4) || cz != (cz = z >> 4)) { - int y = from.getBlockY() + direction.getBlockY(); + int y = from.y() + direction.y(); if (y < singleQueue.getMinY() || y > singleQueue.getMaxY()) { continue; } @@ -320,7 +320,7 @@ public abstract class BreadthFirstSearch implements Operation { } } for (BlockVector3 chunk : chunkLoadSet) { - singleQueue.addChunkLoad(chunk.getBlockX(), chunk.getBlockZ()); + singleQueue.addChunkLoad(chunk.x(), chunk.z()); } } for (BlockVector3 from : queue) { @@ -329,12 +329,12 @@ public abstract class BreadthFirstSearch implements Operation { } for (int i = 0, j = 0; i < dirs.length && j < maxBranch; i++) { BlockVector3 direction = dirs[i]; - int y = from.getBlockY() + direction.getY(); + int y = from.y() + direction.y(); if (y < minY || y > maxY) { continue; } - int x = from.getBlockX() + direction.getX(); - int z = from.getBlockZ() + direction.getZ(); + int x = from.x() + direction.x(); + int z = from.z() + direction.z(); if (!visited.contains(x, y, z)) { if (isVisitable(from, mutable.setComponents(x, y, z))) { j++; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java index f8204b085..2e5f07736 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java @@ -102,8 +102,8 @@ public class DownwardVisitor extends RecursiveVisitor { @Override protected boolean isVisitable(BlockVector3 from, BlockVector3 to) { - int fromY = from.getBlockY(); - return (fromY == baseY || to.subtract(from).getBlockY() < 0) && super.isVisitable(from, to); + int fromY = from.y(); + return (fromY == baseY || to.subtract(from).y() < 0) && super.isVisitable(from, to); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java index ff6b67e03..5ed98c354 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java @@ -111,8 +111,8 @@ public class RegionVisitor implements Operation { while (trailIter.hasNext()) { BlockVector3 pt = trailIter.next(); apply(pt); - int cx = pt.getBlockX() >> 4; - int cz = pt.getBlockZ() >> 4; + int cx = pt.x() >> 4; + int cz = pt.z() >> 4; if (cx != lastTrailChunkX || cz != lastTrailChunkZ) { lastTrailChunkX = cx; lastTrailChunkZ = cz; @@ -128,8 +128,8 @@ public class RegionVisitor implements Operation { lead: for (int count = 0; count < amount; ) { BlockVector3 v = leadIter.next(); - int vcx = v.getBlockX() >> 4; - int vcz = v.getBlockZ() >> 4; + int vcx = v.x() >> 4; + int vcz = v.z() >> 4; if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) { lastLeadChunkX = vcx; lastLeadChunkZ = vcz; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BiomeChange3D.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BiomeChange3D.java index 74a16e90e..4bdbddb4d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BiomeChange3D.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BiomeChange3D.java @@ -33,34 +33,30 @@ import static com.google.common.base.Preconditions.checkNotNull; *

This biome change does not have an {@link Extent} assigned to it because * one will be taken from the passed {@link UndoContext}. If the context * does not have an extent (it is null), cryptic errors may occur.

+ * + * @param position the position + * @param previous the previous biome + * @param current the current biome */ -public class BiomeChange3D implements Change { - - private final BlockVector3 position; - private final BiomeType previous; - private final BiomeType current; +public record BiomeChange3D(BlockVector3 position, BiomeType previous, BiomeType current) implements Change { /** * Create a new biome change. * - * @param position the position - * @param previous the previous biome - * @param current the current biome */ - public BiomeChange3D(BlockVector3 position, BiomeType previous, BiomeType current) { + public BiomeChange3D { checkNotNull(position); checkNotNull(previous); checkNotNull(current); - this.position = position; - this.previous = previous; - this.current = current; } /** * Get the position. * * @return the position + * @deprecated Use {@link #position()}. */ + @Deprecated(forRemoval = true, since = "2.11.0") public BlockVector3 getPosition() { return position; } @@ -69,7 +65,9 @@ public class BiomeChange3D implements Change { * Get the previous biome. * * @return the previous biome + * @deprecated Use {@link #previous()}. */ + @Deprecated(forRemoval = true, since = "2.11.0") public BiomeType getPrevious() { return previous; } @@ -78,7 +76,9 @@ public class BiomeChange3D implements Change { * Get the current biome. * * @return the current biome + * @deprecated Use {@link #current()}. */ + @Deprecated(forRemoval = true, since = "2.11.0") public BiomeType getCurrent() { return current; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BlockChange.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BlockChange.java index ec9bb104d..ecde7967f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BlockChange.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/change/BlockChange.java @@ -34,12 +34,21 @@ import static com.google.common.base.Preconditions.checkNotNull; *

This block change does not have an {@link Extent} assigned to it because * one will be taken from the passed {@link UndoContext}. If the context * does not have an extent (it is null), cryptic errors may occur.

+ * + * @param position the position + * @param previous the previous block + * @param current the current block */ -public class BlockChange implements Change { +public record BlockChange(BlockVector3 position, BaseBlock previous, BaseBlock current) implements Change { - private final BlockVector3 position; - private final BaseBlock previous; - private final BaseBlock current; + /** + * Create a new block change. + */ + public BlockChange { + checkNotNull(position); + checkNotNull(previous); + checkNotNull(current); + } /** * Create a new block change. @@ -53,19 +62,16 @@ public class BlockChange implements Change { BP previous, BC current ) { - checkNotNull(position); - checkNotNull(previous); - checkNotNull(current); - this.position = position; - this.previous = previous.toBaseBlock(); - this.current = current.toBaseBlock(); + this(position, previous.toBaseBlock(), current.toBaseBlock()); } /** * Get the position. * * @return the position + * @deprecated use {@link #position()} */ + @Deprecated(forRemoval = true, since = "2.11.0") public BlockVector3 getPosition() { return position; } @@ -74,7 +80,9 @@ public class BlockChange implements Change { * Get the previous block. * * @return the previous block + * @deprecated use {@link #previous()} */ + @Deprecated(forRemoval = true, since = "2.11.0") public BaseBlock getPrevious() { return previous; } @@ -83,7 +91,9 @@ public class BlockChange implements Change { * Get the current block. * * @return the current block + * @deprecated use {@link #current()} */ + @Deprecated(forRemoval = true, since = "2.11.0") public BaseBlock getCurrent() { return current; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java index ff624e81e..1bad79fb9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java @@ -83,7 +83,7 @@ public class ArrayListHistory implements ChangeSet { if (change instanceof BlockChange) { BlockChange blockChange = (BlockChange) change; BlockVector3 pos = blockChange.getPosition(); - summary.add(pos.getX(), pos.getZ(), blockChange.getCurrent().getOrdinal()); + summary.add(pos.x(), pos.z(), blockChange.getCurrent().getOrdinal()); } } return summary; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/BlockOptimizedHistory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/BlockOptimizedHistory.java index 2019e3022..f358ebfae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/BlockOptimizedHistory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/BlockOptimizedHistory.java @@ -56,7 +56,7 @@ public class BlockOptimizedHistory extends ArrayListHistory { BlockChange blockChange = (BlockChange) change; BlockVector3 position = blockChange.getPosition(); if (!previous.containsLocation(position)) { - previous.add(position, blockChange.getPrevious()); + previous.add(position, blockChange.previous()); } current.add(position, blockChange.getCurrent()); } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java index b4ab9adc1..750324569 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java @@ -81,11 +81,24 @@ public interface ChangeSet extends Closeable { * Get the number of stored changes. * * @return the change count + * @deprecated History could be larger than int max value so FAWE prefers {@link ChangeSet#longSize()} */ + @Deprecated(since = "2.11.1") int size(); //FAWE start + /** + * Get the number of stored changes. + * History could be larger than int max value so FAWE prefers this method. + * + * @return the change count + * @since 2.11.1 + */ + default long longSize() { + return size(); + } + /** * Close the changeset. */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/Constants.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/Constants.java index 0cdd9e8dc..999d646ac 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/Constants.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/Constants.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.internal; -import java.util.Arrays; -import java.util.Collections; import java.util.List; public final class Constants { @@ -35,11 +33,11 @@ public final class Constants { public static final List NO_COPY_ENTITY_NBT_FIELDS; static { - NO_COPY_ENTITY_NBT_FIELDS = Collections.unmodifiableList(Arrays.asList( + NO_COPY_ENTITY_NBT_FIELDS = List.of( "UUIDLeast", "UUIDMost", "UUID", // Bukkit and Vanilla "WorldUUIDLeast", "WorldUUIDMost", // Bukkit and Vanilla "PersistentIDMSB", "PersistentIDLSB" // Forge - )); + ); } /** @@ -86,4 +84,14 @@ public final class Constants { */ public static final int DATA_VERSION_MC_1_20 = 3463; + /** + * The DataVersion for Minecraft 1.21 + */ + public static final int DATA_VERSION_MC_1_21 = 3953; + + /** + * The DataVersion for Minecraft 1.21.3 + */ + public static final int DATA_VERSION_MC_1_21_3 = 4082; + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeleter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeleter.java index e4dcd99ab..1c88a1f2d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeleter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeleter.java @@ -54,7 +54,7 @@ public final class ChunkDeleter { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Comparator chunkSorter = Comparator.comparing( - pos -> (pos.getBlockX() & 31) + (pos.getBlockZ() & 31) * 32 + pos -> (pos.x() & 31) + (pos.z() & 31) * 32 ); private static final Gson chunkDeleterGson = new GsonBuilder() @@ -182,15 +182,15 @@ public final class ChunkDeleter { int startZ = regZ << 5; int endZ = (regZ << 5) + 31; - int minX = Math.max(Math.min(startX, endX), minChunk.getBlockX()); - int minZ = Math.max(Math.min(startZ, endZ), minChunk.getBlockZ()); - int maxX = Math.min(Math.max(startX, endX), maxChunk.getBlockX()); - int maxZ = Math.min(Math.max(startZ, endZ), maxChunk.getBlockZ()); + int minX = Math.max(Math.min(startX, endX), minChunk.x()); + int minZ = Math.max(Math.min(startZ, endZ), minChunk.z()); + int maxX = Math.min(Math.max(startX, endX), maxChunk.x()); + int maxZ = Math.min(Math.max(startZ, endZ), maxChunk.z()); Stream stream = Stream.iterate( BlockVector2.at(minX, minZ), bv2 -> { - int nextX = bv2.getBlockX(); - int nextZ = bv2.getBlockZ(); + int nextX = bv2.x(); + int nextZ = bv2.z(); if (++nextX > maxX) { nextX = minX; if (++nextZ > maxZ) { @@ -295,8 +295,8 @@ public final class ChunkDeleter { @Override public void write(JsonWriter out, BlockVector2 value) throws IOException { out.beginArray(); - out.value(value.getBlockX()); - out.value(value.getBlockZ()); + out.value(value.x()); + out.value(value.z()); out.endArray(); } @@ -317,8 +317,8 @@ public final class ChunkDeleter { private final int z; RegionFilePos(BlockVector2 chunk) { - this.x = chunk.getBlockX() >> 5; - this.z = chunk.getBlockZ() >> 5; + this.x = chunk.x() >> 5; + this.z = chunk.z() >> 5; } RegionFilePos(int regX, int regZ) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeletionInfo.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeletionInfo.java index 13b9d3847..ffcb5f885 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeletionInfo.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/ChunkDeletionInfo.java @@ -45,7 +45,7 @@ public class ChunkDeletionInfo { return chunks.size(); } final BlockVector2 dist = maxChunk.subtract(minChunk).add(1, 1); - return dist.getBlockX() * dist.getBlockZ(); + return dist.x() * dist.z(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/RegionAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/RegionAccess.java index 80eb6989e..7c545040e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/RegionAccess.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/anvil/RegionAccess.java @@ -57,8 +57,8 @@ class RegionAccess implements AutoCloseable { } private static int indexChunk(BlockVector2 pos) { - int x = pos.getBlockX() & 31; - int z = pos.getBlockZ() & 31; + int x = pos.x() & 31; + int z = pos.z() & 31; return x + z * 32; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java index 73f76280e..64e78250a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java @@ -87,16 +87,10 @@ public abstract class ExceptionConverterHelper implements ExceptionConverter { } } - private static class ExceptionHandler implements Comparable { - - final Class cls; - final Method method; - - private ExceptionHandler(Class cls, Method method) { - this.cls = cls; - this.method = method; - } - + private record ExceptionHandler( + Class cls, + Method method + ) implements Comparable { @Override public int compareTo(ExceptionHandler o) { if (cls.equals(o.cls)) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/WorldEditExceptionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/WorldEditExceptionConverter.java index 3f5bfafb5..b3b3b5df8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/WorldEditExceptionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/WorldEditExceptionConverter.java @@ -20,6 +20,9 @@ package com.sk89q.worldedit.internal.command.exception; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.exception.BrushRadiusLimitException; +import com.fastasyncworldedit.core.exception.OutsideWorldBoundsException; +import com.fastasyncworldedit.core.exception.RadiusLimitException; import com.fastasyncworldedit.core.internal.exception.FaweException; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.DisallowedItemException; @@ -36,6 +39,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.InsufficientArgumentsException; import com.sk89q.worldedit.command.tool.InvalidToolBindException; +import com.sk89q.worldedit.extent.clipboard.io.SchematicLoadException; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.formatting.text.Component; @@ -133,6 +137,23 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { ); } + //FAWE start + @ExceptionMatch + public void convert(BrushRadiusLimitException e) throws CommandException { + throw newCommandException(Caption.of("fawe.error.limit.max-brush-radius", TextComponent.of(e.getMaxRadius())), e); + } + + @ExceptionMatch + public void convert(RadiusLimitException e) throws CommandException { + throw newCommandException(Caption.of("fawe.error.limit.max-radius", TextComponent.of(e.getMaxRadius())), e); + } + + @ExceptionMatch + public void convert(OutsideWorldBoundsException e) throws CommandException { + throw newCommandException(Caption.of("fawe.cancel.reason.world.limit", TextComponent.of(e.y())), e); + } + //FAWE end + @ExceptionMatch public void convert(UnknownDirectionException e) throws CommandException { throw newCommandException(e.getRichMessage(), e); @@ -187,6 +208,11 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { throw newCommandException(Caption.of("worldedit.error.file-aborted"), e); } + @ExceptionMatch + public void convert(SchematicLoadException e) throws CommandException { + throw newCommandException(e.getRichMessage(), e); + } + @ExceptionMatch public void convert(WorldEditException e) throws CommandException { throw newCommandException(e.getRichMessage(), e); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionCylinderEvent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionCylinderEvent.java index b9cf79fe0..4150f9a5c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionCylinderEvent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionCylinderEvent.java @@ -42,11 +42,11 @@ public class SelectionCylinderEvent implements CUIEvent { @Override public String[] getParameters() { return new String[]{ - String.valueOf(pos.getBlockX()), - String.valueOf(pos.getBlockY()), - String.valueOf(pos.getBlockZ()), - String.valueOf(radius.getX()), - String.valueOf(radius.getZ()) + String.valueOf(pos.x()), + String.valueOf(pos.y()), + String.valueOf(pos.z()), + String.valueOf(radius.x()), + String.valueOf(radius.z()) }; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionEllipsoidPointEvent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionEllipsoidPointEvent.java index 3bf609b1b..4e0131329 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionEllipsoidPointEvent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionEllipsoidPointEvent.java @@ -40,9 +40,9 @@ public class SelectionEllipsoidPointEvent implements CUIEvent { public String[] getParameters() { return new String[]{ String.valueOf(id), - String.valueOf(pos.getBlockX()), - String.valueOf(pos.getBlockY()), - String.valueOf(pos.getBlockZ()) + String.valueOf(pos.x()), + String.valueOf(pos.y()), + String.valueOf(pos.z()) }; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPoint2DEvent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPoint2DEvent.java index f27eda25c..f01c240a2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPoint2DEvent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPoint2DEvent.java @@ -32,30 +32,30 @@ public class SelectionPoint2DEvent implements CUIEvent { @Deprecated public SelectionPoint2DEvent(int id, BlockVector2 pos, int area) { this.id = id; - this.blockX = pos.getX(); - this.blockZ = pos.getZ(); + this.blockX = pos.x(); + this.blockZ = pos.z(); this.area = area; } @Deprecated public SelectionPoint2DEvent(int id, BlockVector3 pos, int area) { this.id = id; - this.blockX = pos.getX(); - this.blockZ = pos.getZ(); + this.blockX = pos.x(); + this.blockZ = pos.z(); this.area = area; } public SelectionPoint2DEvent(int id, BlockVector2 pos, long area) { this.id = id; - this.blockX = pos.getX(); - this.blockZ = pos.getZ(); + this.blockX = pos.x(); + this.blockZ = pos.z(); this.area = area; } public SelectionPoint2DEvent(int id, BlockVector3 pos, long area) { this.id = id; - this.blockX = pos.getX(); - this.blockZ = pos.getZ(); + this.blockX = pos.x(); + this.blockZ = pos.z(); this.area = area; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPointEvent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPointEvent.java index 1ee2e466d..42718c7ae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPointEvent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/SelectionPointEvent.java @@ -49,9 +49,9 @@ public class SelectionPointEvent implements CUIEvent { public String[] getParameters() { return new String[]{ String.valueOf(id), - String.valueOf(pos.getBlockX()), - String.valueOf(pos.getBlockY()), - String.valueOf(pos.getBlockZ()), + String.valueOf(pos.x()), + String.valueOf(pos.y()), + String.valueOf(pos.z()), String.valueOf(area) }; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java index b9f3891f3..49fac779a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java @@ -29,9 +29,9 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; @@ -79,9 +79,9 @@ public class ServerCUIHandler { try { CuboidRegion region = ((CuboidRegionSelector) regionSelector).getRegion(); - posX = region.getMinimumPoint().getBlockX(); - posY = region.getMinimumPoint().getBlockY(); - posZ = region.getMinimumPoint().getBlockZ(); + posX = region.getMinimumPoint().x(); + posY = region.getMinimumPoint().y(); + posZ = region.getMinimumPoint().z(); width = region.getWidth(); height = region.getHeight(); @@ -104,9 +104,9 @@ public class ServerCUIHandler { } // Just select the point. - posX = point.getBlockX(); - posY = point.getBlockY(); - posZ = point.getBlockZ(); + posX = point.x(); + posY = point.y(); + posZ = point.z(); width = 1; height = 1; length = 1; @@ -128,16 +128,13 @@ public class ServerCUIHandler { double rotX = location.getYaw(); double rotY = location.getPitch(); double xz = Math.cos(Math.toRadians(rotY)); - int x = (int) (location.getX() - (-xz * Math.sin(Math.toRadians(rotX))) * 12); - int z = (int) (location.getZ() - (xz * Math.cos(Math.toRadians(rotX))) * 12); + int x = (int) (location.x() - (-xz * Math.sin(Math.toRadians(rotX))) * 12); + int z = (int) (location.z() - (xz * Math.cos(Math.toRadians(rotX))) * 12); int y = Math.max( player.getWorld().getMinY(), Math.min(Math.min(player.getWorld().getMaxY(), posY + MAX_DISTANCE), posY + 3) ); - //FAWE start - CBT > Map - CompoundBinaryTag.Builder structureTag = CompoundBinaryTag.builder(); - posX -= x; posY -= y; posZ -= z; @@ -147,7 +144,7 @@ public class ServerCUIHandler { return null; } - //FAWE start - see comment of CBT + LinCompoundTag.Builder structureTag = LinCompoundTag.builder(); structureTag.putString("name", "worldedit:" + player.getName()); structureTag.putString("author", player.getName()); structureTag.putString("metadata", ""); @@ -165,7 +162,7 @@ public class ServerCUIHandler { structureTag.putString("mode", "SAVE"); structureTag.putByte("ignoreEntities", (byte) 1); structureTag.putByte("showboundingbox", (byte) 1); - structureTag.putString("id", BlockTypes.STRUCTURE_BLOCK.getId()); + structureTag.putString("id", BlockTypes.STRUCTURE_BLOCK.id()); return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(structureTag.build()); //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/event/InteractionDebouncer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/event/InteractionDebouncer.java new file mode 100644 index 000000000..37e9442b7 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/event/InteractionDebouncer.java @@ -0,0 +1,62 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.event; + +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.util.Identifiable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class InteractionDebouncer { + private final Platform platform; + private final Map lastInteractions = new HashMap<>(); + + public InteractionDebouncer(Platform platform) { + this.platform = platform; + } + + public void clearInteraction(Identifiable player) { + lastInteractions.remove(player.getUniqueId()); + } + + public void setLastInteraction(Identifiable player, boolean result) { + lastInteractions.put(player.getUniqueId(), new Interaction(platform.getTickCount(), result)); + } + + public Optional getDuplicateInteractionResult(Identifiable player) { + Interaction last = lastInteractions.get(player.getUniqueId()); + if (last == null) { + return Optional.empty(); + } + + long now = platform.getTickCount(); + if (now - last.tick <= 1) { + return Optional.of(last.result); + } + + return Optional.empty(); + } + + private record Interaction(long tick, boolean result) { + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExecutionData.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExecutionData.java index 1fef5aa81..bcf04b907 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExecutionData.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExecutionData.java @@ -23,36 +23,23 @@ import java.time.Instant; import static java.util.Objects.requireNonNull; -public class ExecutionData { - +public record ExecutionData(SlotTable slots, Functions functions, Instant deadline) { /** - * Special execution context for evaluating constant values. As long as no variables are used, - * it can be considered constant. + * Special execution context for evaluating constant values. As long as no variables are used, it can be considered + * constant. */ public static final ExecutionData CONSTANT_EVALUATOR = new ExecutionData(null, null, Instant.MAX); - private final SlotTable slots; - private final Functions functions; - private final Instant deadline; - - public ExecutionData(SlotTable slots, Functions functions, Instant deadline) { - this.slots = slots; - this.functions = functions; - this.deadline = deadline; - } - - public SlotTable getSlots() { + @Override + public SlotTable slots() { return requireNonNull(slots, "Cannot use variables in a constant"); } - public Functions getFunctions() { + @Override + public Functions functions() { return requireNonNull(functions, "Cannot use functions in a constant"); } - public Instant getDeadline() { - return deadline; - } - public void checkDeadline() { if (Instant.now().isAfter(deadline)) { throw new ExpressionTimeoutException("Calculations exceeded time limit."); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java index b7ce1acf3..23ba96a88 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.antlr.ExpressionLexer; import com.sk89q.worldedit.antlr.ExpressionParser; import com.sk89q.worldedit.internal.expression.invoke.ExpressionCompiler; +import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -199,7 +200,9 @@ public class Expression implements Cloneable { //FAWE start public Expression clone() { - return new Expression(initialExpression, new HashSet<>(providedSlots)); + Expression expression = new Expression(initialExpression, new HashSet<>(providedSlots)); + expression.setEnvironment(getEnvironment().clone()); + return expression; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionEnvironment.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionEnvironment.java index 061a520a9..5e44d9da1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionEnvironment.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionEnvironment.java @@ -22,7 +22,7 @@ package com.sk89q.worldedit.internal.expression; /** * Represents a way to access blocks in a world. Has to accept non-rounded coordinates. */ -public interface ExpressionEnvironment { +public interface ExpressionEnvironment extends Cloneable { int getBlockType(double x, double y, double z); @@ -36,4 +36,7 @@ public interface ExpressionEnvironment { int getBlockDataRel(double x, double y, double z); + // FAWE start + ExpressionEnvironment clone(); + // FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java index 0afeb6dd3..0521c0a50 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java @@ -40,6 +40,12 @@ public class ExpressionHelper { } } + public static void check(boolean condition, int positionInLine, String message) { + if (!condition) { + throw evalException(positionInLine, message); + } + } + public static int getErrorPosition(Token token) { return token.getCharPositionInLine(); } @@ -49,14 +55,18 @@ public class ExpressionHelper { } public static EvaluationException evalException(Token token, String message) { + return evalException(getErrorPosition(token), message); + } + + public static EvaluationException evalException(int positionInLine, String message) { return new EvaluationException( - getErrorPosition(token), - message + positionInLine, + message ); } - public static void checkIterations(int iterations, ParserRuleContext ctx) { - check(iterations <= 256, ctx, "Loop exceeded 256 iterations"); + public static void checkIterations(int iterations, int positionInLine) { + check(iterations <= 256, positionInLine, "Loop exceeded 256 iterations"); } public static MethodHandle resolveFunction( @@ -72,10 +82,10 @@ public class ExpressionHelper { // last param is the array, turn that varargs int keptParams = nParams - 1; function = function.asCollector( - // collect into the last array - function.type().parameterType(nParams - 1), - // collect the variable args (args over kept) - ctx.args.size() - keptParams + // collect into the last array + function.type().parameterType(nParams - 1), + // collect the variable args (args over kept) + ctx.args.size() - keptParams ); // re-wrap it for the inner arguments function = function.asType(function.type().wrap()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java index 6f3a63787..ef219e3f8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java @@ -211,8 +211,8 @@ public final class Functions { final double cosF = Math.cos(angle); final double sinF = Math.sin(angle); - final double xOld = x.getValue(); - final double yOld = y.getValue(); + final double xOld = x.value(); + final double yOld = y.value(); x.setValue(xOld * cosF - yOld * sinF); y.setValue(xOld * sinF + yOld * cosF); @@ -221,9 +221,9 @@ public final class Functions { } private static double swap(Variable x, Variable y) { - final double tmp = x.getValue(); + final double tmp = x.value(); - x.setValue(y.getValue()); + x.setValue(y.value()); y.setValue(tmp); return 0.0; @@ -391,8 +391,8 @@ public final class Functions { private static double queryInternal(LocalSlot type, LocalSlot data, double typeId, double dataValue) { // Compare to input values and determine return value // -1 is a wildcard, always true - double ret = ((type.getValue() == -1 || typeId == type.getValue()) - && (data.getValue() == -1 || dataValue == data.getValue())) ? 1.0 : 0.0; + double ret = ((type.value() == -1 || typeId == type.value()) + && (data.value() == -1 || dataValue == data.value())) ? 1.0 : 0.0; if (type instanceof Variable) { ((Variable) type).setValue(typeId); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java index 2b02fa036..0b2a5bc48 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java @@ -24,19 +24,7 @@ package com.sk89q.worldedit.internal.expression; */ public interface LocalSlot { - final class Constant implements LocalSlot { - - private final double value; - - public Constant(double value) { - this.value = value; - } - - @Override - public double getValue() { - return value; - } - + record Constant(double value) implements LocalSlot { @Override public String toString() { return String.valueOf(value); @@ -57,7 +45,7 @@ public interface LocalSlot { } @Override - public double getValue() { + public double value() { return value; } @@ -65,9 +53,8 @@ public interface LocalSlot { public String toString() { return String.valueOf(value); } - } - double getValue(); + double value(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java index a94c9dc62..e7090f461 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java @@ -58,7 +58,7 @@ public class SlotTable { public OptionalDouble getSlotValue(String name) { LocalSlot slot = slots.get(name); - return slot == null ? OptionalDouble.empty() : OptionalDouble.of(slot.getValue()); + return slot == null ? OptionalDouble.empty() : OptionalDouble.of(slot.value()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/CompilingVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/CompilingVisitor.java index 7645c8413..0c6e87810 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/CompilingVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/CompilingVisitor.java @@ -106,7 +106,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { if (ctx.parent instanceof ParserRuleContext) { checkHandle(mh, (ParserRuleContext) ctx.parent); } - return new ExecNode(ctx, mh); + return new ExecNode(ctx.start.getCharPositionInLine(), mh); } private void checkHandle(MethodHandle mh, ParserRuleContext ctx) { @@ -127,7 +127,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { MethodHandles.identity(Double.class) ); // now pass `result` into `guard` - MethodHandle result = evaluate(ctx).handle; + MethodHandle result = evaluate(ctx).handle(); return MethodHandles.collectArguments(guard, 0, result); } @@ -151,8 +151,8 @@ class CompilingVisitor extends ExpressionBaseVisitor { // easiest one of the bunch return MethodHandles.guardWithTest( evaluateBoolean(condition), - trueBranch == null ? NULL_DOUBLE : evaluate(trueBranch).handle, - falseBranch == null ? NULL_DOUBLE : evaluate(falseBranch).handle + trueBranch == null ? NULL_DOUBLE : evaluate(trueBranch).handle(), + falseBranch == null ? NULL_DOUBLE : evaluate(falseBranch).handle() ); } @@ -185,10 +185,10 @@ class CompilingVisitor extends ExpressionBaseVisitor { @Override public MethodHandle visitForStatement(ExpressionParser.ForStatementContext ctx) { return ExpressionHandles.forLoop( - evaluate(ctx.init).handle, + evaluate(ctx.init).handle(), evaluateBoolean(ctx.condition), evaluate(ctx.body), - evaluate(ctx.update).handle + evaluate(ctx.update).handle() ); } @@ -235,7 +235,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { RETURN_STATEMENT_BASE, 0, // map the Double back to ExecutionData via the returnValue - evaluate(ctx.value).handle + evaluate(ctx.value).handle() ); } @@ -262,7 +262,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { @Override public MethodHandle visitExpressionStatement(ExpressionParser.ExpressionStatementContext ctx) { - return evaluate(ctx.expression()).handle; + return evaluate(ctx.expression()).handle(); } @Override @@ -271,7 +271,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { int opType = ctx.op.getType(); return ExpressionHandles.call(data -> { LocalSlot.Variable variable = ExpressionHandles.getVariable(data, target); - double value = variable.getValue(); + double value = variable.value(); double result = value; if (opType == INCREMENT) { value++; @@ -289,7 +289,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { int opType = ctx.op.getType(); return ExpressionHandles.call(data -> { LocalSlot.Variable variable = ExpressionHandles.getVariable(data, target); - double value = variable.getValue(); + double value = variable.value(); if (opType == INCREMENT) { value++; } else { @@ -547,7 +547,7 @@ class CompilingVisitor extends ExpressionBaseVisitor { value = arg; } else { variable = ExpressionHandles.getVariable(data, target); - value = variable.getValue(); + value = variable.value(); switch (type) { case POWER_ASSIGN: value = Math.pow(value, arg); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExecNode.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExecNode.java index 6c53a13e5..86a944f03 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExecNode.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExecNode.java @@ -19,18 +19,7 @@ package com.sk89q.worldedit.internal.expression.invoke; -import org.antlr.v4.runtime.ParserRuleContext; - import java.lang.invoke.MethodHandle; -class ExecNode { - - final ParserRuleContext ctx; - final MethodHandle handle; - - ExecNode(ParserRuleContext ctx, MethodHandle handle) { - this.ctx = ctx; - this.handle = handle; - } - +record ExecNode(int positionInLine, MethodHandle handle) { } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExpressionHandles.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExpressionHandles.java index a2d0ad483..dab0be01b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExpressionHandles.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/invoke/ExpressionHandles.java @@ -200,7 +200,7 @@ class ExpressionHandles { static LocalSlot.Variable initVariable(ExecutionData data, Token nameToken) { String name = nameToken.getText(); - return data.getSlots().initVariable(name) + return data.slots().initVariable(name) .orElseThrow(() -> ExpressionHelper.evalException( nameToken, "Cannot overwrite non-variable '" + name + "'" )); @@ -218,7 +218,7 @@ class ExpressionHandles { static LocalSlot.Variable getVariable(ExecutionData data, Token nameToken) { String name = nameToken.getText(); - LocalSlot slot = data.getSlots().getSlot(name) + LocalSlot slot = data.slots().getSlot(name) .orElseThrow(varNotInitException(nameToken)); if (!(slot instanceof LocalSlot.Variable)) { throw ExpressionHelper.evalException( @@ -230,7 +230,7 @@ class ExpressionHandles { static double getSlotValue(ExecutionData data, Token nameToken) { String name = nameToken.getText(); - return data.getSlots().getSlotValue(name) + return data.slots().getSlotValue(name) .orElseThrow(varNotInitException(nameToken)); } @@ -302,11 +302,11 @@ class ExpressionHandles { standardInvoke(init, data); } while ((boolean) standardInvoke(condition, data)) { - checkIterations(iterations, body.ctx); + checkIterations(iterations, body.positionInLine()); data.checkDeadline(); iterations++; try { - result = (Double) standardInvoke(body.handle, data); + result = (Double) standardInvoke(body.handle(), data); } catch (BreakException ex) { if (!ex.doContinue) { break; @@ -331,11 +331,11 @@ class ExpressionHandles { Double result = null; int iterations = 0; do { - checkIterations(iterations, body.ctx); + checkIterations(iterations, body.positionInLine()); data.checkDeadline(); iterations++; try { - result = (Double) standardInvoke(body.handle, data); + result = (Double) standardInvoke(body.handle(), data); } catch (BreakException ex) { if (!ex.doContinue) { break; @@ -369,12 +369,12 @@ class ExpressionHandles { double last = (double) standardInvoke(getLast, data); LocalSlot.Variable variable = initVariable(data, counterToken); for (double i = first; i <= last; i++) { - checkIterations(iterations, body.ctx); + checkIterations(iterations, body.positionInLine()); data.checkDeadline(); iterations++; variable.setValue(i); try { - result = (Double) standardInvoke(body.handle, data); + result = (Double) standardInvoke(body.handle(), data); } catch (BreakException ex) { if (!ex.doContinue) { break; @@ -406,10 +406,10 @@ class ExpressionHandles { if (falling || entry.getDoubleKey() == value) { matched = true; try { - evaluated = (Double) standardInvoke(entry.getValue().handle, data); + evaluated = (Double) standardInvoke(entry.getValue().handle(), data); falling = true; } catch (BreakException brk) { - check(!brk.doContinue, entry.getValue().ctx, "Cannot continue in a switch"); + check(!brk.doContinue, entry.getValue().positionInLine(), "Cannot continue in a switch"); falling = false; break; } @@ -418,9 +418,9 @@ class ExpressionHandles { // This if is like the one in the loop, default's "case" is `!matched` & present if ((falling || !matched) && defaultCase != null) { try { - evaluated = (Double) standardInvoke(defaultCase.handle, data); + evaluated = (Double) standardInvoke(defaultCase.handle(), data); } catch (BreakException brk) { - check(!brk.doContinue, defaultCase.ctx, "Cannot continue in a switch"); + check(!brk.doContinue, defaultCase.positionInLine(), "Cannot continue in a switch"); } } return evaluated; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java index ef4299b33..75fae8ca2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java @@ -21,6 +21,9 @@ package com.sk89q.worldedit.internal.registry; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser; +import com.fastasyncworldedit.core.extension.factory.parser.FaweParser; +import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser; +import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.NoMatchException; @@ -43,7 +46,10 @@ import static com.google.common.base.Preconditions.checkNotNull; public abstract class AbstractFactory { protected final WorldEdit worldEdit; - private final List> parsers = new ArrayList<>(); + //FAWE start + protected final List> parsers = new ArrayList<>(); + private final FaweParser richParser; + //FWAE end /** * Create a new factory. @@ -52,11 +58,26 @@ public abstract class AbstractFactory { * @param defaultParser the parser to fall back to */ protected AbstractFactory(WorldEdit worldEdit, InputParser defaultParser) { + //FAWE start + this(worldEdit, defaultParser, null); + } + + /** + * Create a new factory with a given rich parser for FAWE rich parsing + * + * @param worldEdit the WorldEdit instance + * @param defaultParser the parser to fall back to + * @param richParser the rich parser + * @since 2.11.0 + */ + protected AbstractFactory(WorldEdit worldEdit, InputParser defaultParser, FaweParser richParser) { checkNotNull(worldEdit); checkNotNull(defaultParser); this.worldEdit = worldEdit; this.parsers.add(defaultParser); + this.richParser = richParser; } + //FAWE end /** * Gets an immutable list of parsers. @@ -71,7 +92,7 @@ public abstract class AbstractFactory { return Collections.unmodifiableList(parsers); } - //FAWE start - javadoc + //FAWE start /** * Parse a string and context to each {@link InputParser} added to this factory. If no result found, throws {@link InputParseException} @@ -81,24 +102,35 @@ public abstract class AbstractFactory { * @return parsed result * @throws InputParseException if no result found */ - //FAWE end public E parseFromInput(String input, ParserContext context) throws InputParseException { - E match; - - for (InputParser parser : parsers) { - match = parser.parseFromInput(input, context); - - if (match != null) { - return match; + List parsed = new ArrayList<>(); + for (String component : StringUtil.split(input,' ', '[', ']')) { + if (component.isEmpty()) { + continue; } + + if (richParser != null) { + E match = richParser.parseFromInput(component, context); + if (match != null) { + parsed.add(match); + continue; + } + } + parseFromParsers(context, parsed, component); } - throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); + return getParsed(input, parsed); + } + //FAWE end + + @Deprecated + public List getSuggestions(String input) { + return getSuggestions(input, new ParserContext()); } - public List getSuggestions(String input) { + public List getSuggestions(String input, ParserContext context) { return parsers.stream().flatMap( - p -> p.getSuggestions(input) + p -> p.getSuggestions(input, context) ).collect(Collectors.toList()); } @@ -128,4 +160,48 @@ public abstract class AbstractFactory { }); } + //FAWE start + protected void parseFromParsers(final ParserContext context, final List parsed, final String component) { + E match = null; + for (InputParser parser : getParsers()) { + match = parser.parseFromInput(component, context); + + if (match != null) { + break; + } + } + if (match == null) { + throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component))); + } + parsed.add(match); + } + + /** + * Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting + * "richer" parsing where & and , are used. Exists to prevent stack overflows. + * + * @param input input string + * @param context input context + * @return parsed result + * @throws InputParseException if no result found + */ + public E parseWithoutRich(String input, ParserContext context) throws InputParseException { + List parsed = new ArrayList<>(); + + for (String component : StringUtil.split(input, ' ', '[', ']')) { + if (component.isEmpty()) { + continue; + } + + parseFromParsers(context, parsed, component); + } + + return getParsed(input, parsed); + } + + protected E getParsed(final String input, final List parsed) { + return parsed.isEmpty() ? null : parsed.get(0); + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java index 87829a272..57ec3a247 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java @@ -45,9 +45,22 @@ public abstract class InputParser { * Gets a stream of suggestions of input to this parser. * * @return a stream of suggestions + * @deprecated Use the version that takes a {@link ParserContext}, {@link #getSuggestions(String, ParserContext)} */ + @Deprecated public Stream getSuggestions(String input) { return Stream.empty(); } + /** + * Gets a stream of suggestions of input to this parser. + * + * @param input The string input + * @param context The parser context + * + * @return a stream of suggestions + */ + public Stream getSuggestions(String input, ParserContext context) { + return getSuggestions(input); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/ClipboardTransformBaker.java similarity index 75% rename from worldedit-core/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/ClipboardTransformBaker.java index 14e3d3307..daa969080 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/ClipboardTransformBaker.java @@ -17,13 +17,16 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.command; +package com.sk89q.worldedit.internal.util; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.CombinedTransform; @@ -36,12 +39,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Helper class to 'bake' a transform into a clipboard. * - *

This class needs a better name and may need to be made more generic.

- * * @see Clipboard * @see Transform */ -public class FlattenedClipboardTransform { +public class ClipboardTransformBaker { private final Clipboard original; private final Transform transform; @@ -52,7 +53,7 @@ public class FlattenedClipboardTransform { * @param original the original clipboard * @param transform the transform */ - private FlattenedClipboardTransform(Clipboard original, Transform transform) { + private ClipboardTransformBaker(Clipboard original, Transform transform) { checkNotNull(original); checkNotNull(transform); this.original = original; @@ -64,7 +65,7 @@ public class FlattenedClipboardTransform { * * @return the transformed region */ - public Region getTransformedRegion() { + private Region getTransformedRegion() { Region region = original.getRegion(); Vector3 minimum = region.getMinimumPoint().toVector3(); Vector3 maximum = region.getMaximumPoint().toVector3(); @@ -73,18 +74,17 @@ public class FlattenedClipboardTransform { new CombinedTransform( new AffineTransform().translate(original.getOrigin().multiply(-1)), transform, - new AffineTransform().translate(original.getOrigin()) - ); + new AffineTransform().translate(original.getOrigin())); Vector3[] corners = new Vector3[]{ minimum, maximum, - minimum.withX(maximum.getX()), - minimum.withY(maximum.getY()), - minimum.withZ(maximum.getZ()), - maximum.withX(minimum.getX()), - maximum.withY(minimum.getY()), - maximum.withZ(minimum.getZ()) + minimum.withX(maximum.x()), + minimum.withY(maximum.y()), + minimum.withZ(maximum.z()), + maximum.withX(minimum.x()), + maximum.withY(minimum.y()), + maximum.withZ(minimum.z()) }; for (int i = 0; i < corners.length; i++) { @@ -113,7 +113,7 @@ public class FlattenedClipboardTransform { * @param target the target * @return the operation */ - public Operation copyTo(Extent target) { + private Operation copyTo(Extent target) { //FAWE start Extent extent = original; if (transform != null && !transform.isIdentity()) { @@ -121,11 +121,7 @@ public class FlattenedClipboardTransform { } //FAWE end ForwardExtentCopy copy = new ForwardExtentCopy( - extent, - original.getRegion(), - original.getOrigin(), - target, - original.getOrigin() + extent, original.getRegion(), original.getOrigin(), target, original.getOrigin() ); copy.setTransform(transform); if (original.hasBiomes()) { @@ -140,9 +136,18 @@ public class FlattenedClipboardTransform { * @param original the original clipboard * @param transform the transform * @return a builder + * @throws WorldEditException if an error occurred during copy */ - public static FlattenedClipboardTransform transform(Clipboard original, Transform transform) { - return new FlattenedClipboardTransform(original, transform); + public static Clipboard bakeTransform(Clipboard original, Transform transform) throws WorldEditException { + if (transform.isIdentity()) { + return original; + } + ClipboardTransformBaker baker = new ClipboardTransformBaker(original, transform); + Clipboard target = new BlockArrayClipboard(baker.getTransformedRegion()); + target.setOrigin(original.getOrigin()); + Operations.complete(baker.copyTo(target)); + + return target; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorter.java index b30bd8f49..4fdcb2118 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorter.java @@ -62,13 +62,13 @@ public class RegionOptimizedVectorSorter { private static final long FLIP_REGION_Z_SIGN = 0x1_00_00L << REGION_Z_SHIFT; private static long key(BlockVector3 elem) { - long x = elem.getX(); - long z = elem.getZ(); + long x = elem.x(); + long z = elem.z(); return (((x << (REGION_X_SHIFT - 9)) & REGION_X_MASK) ^ FLIP_REGION_X_SIGN) | (((z << (REGION_Z_SHIFT - 9)) & REGION_Z_MASK) ^ FLIP_REGION_Z_SIGN) | ((x << (CHUNK_X_SHIFT - 4)) & CHUNK_X_MASK) | ((z << (CHUNK_Z_SHIFT - 4)) & CHUNK_Z_MASK) - | (Y_MAX - elem.getY()); + | (Y_MAX - elem.y()); } private static final int NUMBER_OF_BITS = 64; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/VarIntIterator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/VarIntIterator.java new file mode 100644 index 000000000..ac91c8365 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/VarIntIterator.java @@ -0,0 +1,81 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.util; + +import it.unimi.dsi.fastutil.ints.IntIterator; + +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +/** + * Simple class to transform a {@code byte[]} into an iterator of the VarInts encoded in it. + */ +public class VarIntIterator implements PrimitiveIterator.OfInt { + + private final byte[] source; + private int index; + private boolean hasNextInt; + private int nextInt; + + public VarIntIterator(byte[] source) { + this.source = source; + } + + @Override + public boolean hasNext() { + if (hasNextInt) { + return true; + } + if (index >= source.length) { + return false; + } + + nextInt = readNextInt(); + return hasNextInt = true; + } + + private int readNextInt() { + int value = 0; + for (int bitsRead = 0; ; bitsRead += 7) { + if (index >= source.length) { + throw new IllegalStateException("Ran out of bytes while reading VarInt (probably corrupted data)"); + } + byte next = source[index]; + index++; + value |= (next & 0x7F) << bitsRead; + if (bitsRead > 7 * 5) { + throw new IllegalStateException("VarInt too big (probably corrupted data)"); + } + if ((next & 0x80) == 0) { + break; + } + } + return value; + } + + @Override + public int nextInt() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + hasNextInt = false; + return nextInt; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java index 769773b96..097db6964 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java @@ -19,17 +19,14 @@ package com.sk89q.worldedit.internal.wna; -import com.google.common.collect.ImmutableMap; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.StringBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; @@ -50,9 +47,9 @@ public interface WorldNativeAccess { checkNotNull(block); setCurrentSideEffectSet(sideEffects); - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); + int x = position.x(); + int y = position.y(); + int z = position.z(); // First set the block NC chunk = getChunk(x >> 4, z >> 4); @@ -68,17 +65,15 @@ public interface WorldNativeAccess { // Create the TileEntity if (successful || old == newState) { - if (block instanceof BaseBlock) { - BaseBlock baseBlock = (BaseBlock) block; - //FAWE start - use CompoundBinaryTag over CompoundTag - CompoundBinaryTag tag = baseBlock.getNbt(); + if (block instanceof BaseBlock baseBlock) { + LinCompoundTag tag = baseBlock.getNbt(); if (tag != null) { - tag = tag.put(ImmutableMap.of( - "id", StringBinaryTag.of(baseBlock.getNbtId()), - "x", IntBinaryTag.of(position.getX()), - "y", IntBinaryTag.of(position.getY()), - "z", IntBinaryTag.of(position.getZ()) - )); + tag = tag.toBuilder() + .putString("id", baseBlock.getNbtId()) + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .build(); // update if TE changed as well successful = updateTileEntity(pos, tag); @@ -99,8 +94,8 @@ public interface WorldNativeAccess { default void applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) { setCurrentSideEffectSet(sideEffectSet); - NP pos = getPosition(position.getX(), position.getY(), position.getZ()); - NC chunk = getChunk(position.getX() >> 4, position.getZ() >> 4); + NP pos = getPosition(position.x(), position.y(), position.z()); + NC chunk = getChunk(position.x() >> 4, position.z() >> 4); NBS oldData = toNative(previousType); NBS newData = getBlockState(chunk, pos); @@ -143,7 +138,7 @@ public interface WorldNativeAccess { void updateLightingForBlock(NP position); - boolean updateTileEntity(NP position, CompoundBinaryTag tag); + boolean updateTileEntity(NP position, LinCompoundTag tag); void notifyBlockUpdate(NC chunk, NP position, NBS oldState, NBS newState); @@ -151,7 +146,9 @@ public interface WorldNativeAccess { void markBlockChanged(NC chunk, NP position); - void notifyNeighbors(NP pos, NBS oldState, NBS newState); + void notifyNeighbors(NP pos, NBS oldState, NBS newState);; + + void updateBlock(NP pos, NBS oldState, NBS newState); void updateNeighbors(NP pos, NBS oldState, NBS newState, int recursionLimit); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector2.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector2.java index fe95ad3ad..7db9cd7e2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector2.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector2.java @@ -27,7 +27,7 @@ import java.util.Comparator; /** * An immutable 2-dimensional vector. */ -//FAWE start - un-finalize +//FAWE start - not a record public class BlockVector2 { //FAWE end @@ -53,7 +53,7 @@ public class BlockVector2 { * */ public static final Comparator COMPARING_GRID_ARRANGEMENT = - Comparator.comparingInt(BlockVector2::getZ).thenComparingInt(BlockVector2::getX); + Comparator.comparingInt(BlockVector2::z).thenComparingInt(BlockVector2::x); public static BlockVector2 at(double x, double z) { return at((int) Math.floor(x), (int) Math.floor(z)); @@ -122,7 +122,19 @@ public class BlockVector2 { * Get the X coordinate. * * @return the x coordinate + * @since 2.11.0 */ + public int x() { + return x; + } + + /** + * Get the X coordinate. + * + * @return the x coordinate + * @deprecated use {@link #x()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getX() { return x; } @@ -131,7 +143,9 @@ public class BlockVector2 { * Get the X coordinate. * * @return the x coordinate + * @deprecated use {@link #x()} instead */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getBlockX() { return x; } @@ -150,7 +164,19 @@ public class BlockVector2 { * Get the Z coordinate. * * @return the z coordinate + * @since 2.11.0 */ + public int z() { + return z; + } + + /** + * Get the Z coordinate. + * + * @return the z coordinate + * @deprecated use {@link #z()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getZ() { return z; } @@ -159,7 +185,9 @@ public class BlockVector2 { * Get the Z coordinate. * * @return the z coordinate + * @deprecated use {@link #z()} instead */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getBlockZ() { return z; } @@ -598,13 +626,13 @@ public class BlockVector2 { return BlockVector3.at(x, y, z); } + //FAWE start - not a record, need own implementations @Override public boolean equals(Object obj) { - if (!(obj instanceof BlockVector2)) { + if (!(obj instanceof BlockVector2 other)) { return false; } - BlockVector2 other = (BlockVector2) obj; return other.x == this.x && other.z == this.z; } @@ -613,6 +641,7 @@ public class BlockVector2 { public int hashCode() { return (x << 16) ^ z; } + //FAWE end @Override public String toString() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index 5f1c14842..017ec7ca0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -38,7 +38,9 @@ import static com.sk89q.worldedit.math.BitMath.unpackZ; /** * An immutable 3-dimensional vector. */ +//FAWE start - not a record public abstract class BlockVector3 { +//FAWE end public static final BlockVector3 ZERO = BlockVector3.at(0, 0, 0); public static final BlockVector3 UNIT_X = BlockVector3.at(1, 0, 0); @@ -85,9 +87,9 @@ public abstract class BlockVector3 { } public static boolean isLongPackable(BlockVector3 location) { - return isHorizontallyInBounds(location.getX()) - && isHorizontallyInBounds(location.getZ()) - && WORLD_Y_MIN <= location.getY() && location.getY() <= WORLD_Y_MAX; + return isHorizontallyInBounds(location.x()) + && isHorizontallyInBounds(location.z()) + && WORLD_Y_MIN <= location.y() && location.y() <= WORLD_Y_MAX; } public static void checkLongPackable(BlockVector3 location) { @@ -107,9 +109,9 @@ public abstract class BlockVector3 { private static final class YzxOrderComparator { private static final Comparator YZX_ORDER = - Comparator.comparingInt(BlockVector3::getY) - .thenComparingInt(BlockVector3::getZ) - .thenComparingInt(BlockVector3::getX); + Comparator.comparingInt(BlockVector3::y) + .thenComparingInt(BlockVector3::z) + .thenComparingInt(BlockVector3::x); } @@ -135,57 +137,69 @@ public abstract class BlockVector3 { public long toLongPackedForm() { checkLongPackable(this); - return (getX() & BITS_26) | ((getZ() & BITS_26) << 26) | (((getY() & BITS_12) << (26 + 26))); + return (x() & BITS_26) | ((z() & BITS_26) << 26) | (((y() & BITS_12) << (26 + 26))); } public MutableBlockVector3 mutX(double x) { - return new MutableBlockVector3((int) x, getY(), getZ()); + return new MutableBlockVector3((int) x, y(), z()); } public MutableBlockVector3 mutY(double y) { - return new MutableBlockVector3(getX(), (int) y, getZ()); + return new MutableBlockVector3(x(), (int) y, z()); } public MutableBlockVector3 mutZ(double z) { - return new MutableBlockVector3(getX(), getY(), (int) z); + return new MutableBlockVector3(x(), y(), (int) z); } public MutableBlockVector3 mutX(int x) { - return new MutableBlockVector3(x, getY(), getZ()); + return new MutableBlockVector3(x, y(), z()); } public MutableBlockVector3 mutY(int y) { - return new MutableBlockVector3(getX(), y, getZ()); + return new MutableBlockVector3(x(), y, z()); } public MutableBlockVector3 mutZ(int z) { - return new MutableBlockVector3(getX(), getY(), z); + return new MutableBlockVector3(x(), y(), z); } public BlockVector3 toImmutable() { - return BlockVector3.at(getX(), getY(), getZ()); + return BlockVector3.at(x(), y(), z()); } //FAWE end + //FAWE start - make record getters to abstract methods /** * Get the X coordinate. * * @return the x coordinate + * @since 2.11.0 */ - //FAWE start - Made abstract - public abstract int getX(); + public abstract int x(); //FAWE end /** * Get the X coordinate. * * @return the x coordinate + * @deprecated use {@link #x()} instead */ - //FAWE start - getter + @Deprecated(forRemoval = true, since = "2.11.0") + public int getX() { + return this.x(); //FAWE - access abstract getter instead of local field + } + + /** + * Get the X coordinate. + * + * @return the x coordinate + * @deprecated use {@link #x()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getBlockX() { - return getX(); + return this.x(); //FAWE - access abstract getter instead of local field } - //FAWE end /** * Set the X coordinate. @@ -195,29 +209,42 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 withX(int x) { - return BlockVector3.at(x, getY(), getZ()); + return BlockVector3.at(x, y(), z()); } //FAWE end + + //FAWE start - make record getters to abstract methods /** * Get the Y coordinate. * * @return the y coordinate + * @since 2.11.0 */ - //FAWE start - Made abstract - public abstract int getY(); + public abstract int y(); //FAWE end /** * Get the Y coordinate. * * @return the y coordinate + * @deprecated use {@link #y()} instead */ - //FAWE start - getter + @Deprecated(forRemoval = true, since = "2.11.0") + public int getY() { + return this.y(); //FAWE - access abstract getter instead of local field + } + + /** + * Get the Y coordinate. + * + * @return the y coordinate + * @deprecated use {@link #y()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getBlockY() { - return getY(); + return this.y(); //FAWE - access abstract getter instead of local field } - //FAWE end /** * Set the Y coordinate. @@ -227,29 +254,41 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 withY(int y) { - return BlockVector3.at(getX(), y, getZ()); + return BlockVector3.at(x(), y, z()); } //FAWE end + //FAWE start - make record getters to abstract methods /** * Get the Z coordinate. * - * @return the z coordinate + * @return the Z coordinate + * @since 2.11.0 */ - //FAWE start - Made abstract - public abstract int getZ(); + public abstract int z(); //FAWE end /** * Get the Z coordinate. * * @return the z coordinate + * @deprecated use {@link #z()} instead */ - //FAWE start - getter + @Deprecated(forRemoval = true, since = "2.11.0") + public int getZ() { + return this.z(); //FAWE - access abstract getter instead of local field + } + + /** + * Get the Z coordinate. + * + * @return the z coordinate + * @deprecated use {@link #z()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") public int getBlockZ() { - return getZ(); + return this.z(); //FAWE - access abstract getter instead of local field } - //FAWE end /** * Set the Z coordinate. @@ -259,7 +298,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 withZ(int z) { - return BlockVector3.at(getX(), getY(), z); + return BlockVector3.at(x(), y(), z); } //FAWE end @@ -271,7 +310,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 add(BlockVector3 other) { - return add(other.getX(), other.getY(), other.getZ()); + return add(other.x(), other.y(), other.z()); } //FAWE end @@ -285,7 +324,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 add(int x, int y, int z) { - return BlockVector3.at(this.getX() + x, this.getY() + y, this.getZ() + z); + return BlockVector3.at(this.x() + x, this.y() + y, this.z() + z); } //FAWE end @@ -298,14 +337,14 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 add(BlockVector3... others) { - int newX = getX(); - int newY = getY(); - int newZ = getZ(); + int newX = x(); + int newY = y(); + int newZ = z(); for (BlockVector3 other : others) { - newX += other.getX(); - newY += other.getY(); - newZ += other.getZ(); + newX += other.x(); + newY += other.y(); + newZ += other.z(); } return BlockVector3.at(newX, newY, newZ); @@ -321,7 +360,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 subtract(BlockVector3 other) { - return subtract(other.getX(), other.getY(), other.getZ()); + return subtract(other.x(), other.y(), other.z()); } //FAWE end @@ -336,7 +375,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 subtract(int x, int y, int z) { - return BlockVector3.at(this.getX() - x, this.getY() - y, this.getZ() - z); + return BlockVector3.at(this.x() - x, this.y() - y, this.z() - z); } //FAWE end @@ -349,14 +388,14 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 subtract(BlockVector3... others) { - int newX = getX(); - int newY = getY(); - int newZ = getZ(); + int newX = x(); + int newY = y(); + int newZ = z(); for (BlockVector3 other : others) { - newX -= other.getX(); - newY -= other.getY(); - newZ -= other.getZ(); + newX -= other.x(); + newY -= other.y(); + newZ -= other.z(); } return BlockVector3.at(newX, newY, newZ); @@ -371,7 +410,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 multiply(BlockVector3 other) { - return multiply(other.getX(), other.getY(), other.getZ()); + return multiply(other.x(), other.y(), other.z()); } //FAWE end @@ -385,7 +424,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 multiply(int x, int y, int z) { - return BlockVector3.at(this.getX() * x, this.getY() * y, this.getZ() * z); + return BlockVector3.at(this.x() * x, this.y() * y, this.z() * z); } //FAWE end @@ -397,14 +436,14 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 multiply(BlockVector3... others) { - int newX = getX(); - int newY = getY(); - int newZ = getZ(); + int newX = x(); + int newY = y(); + int newZ = z(); for (BlockVector3 other : others) { - newX *= other.getX(); - newY *= other.getY(); - newZ *= other.getZ(); + newX *= other.x(); + newY *= other.y(); + newZ *= other.z(); } return BlockVector3.at(newX, newY, newZ); @@ -429,7 +468,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 divide(BlockVector3 other) { - return divide(other.getX(), other.getY(), other.getZ()); + return divide(other.x(), other.y(), other.z()); } //FAWE end @@ -443,7 +482,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 divide(int x, int y, int z) { - return BlockVector3.at(this.getX() / x, this.getY() / y, this.getZ() / z); + return BlockVector3.at(this.x() / x, this.y() / y, this.z() / z); } //FAWE end @@ -467,7 +506,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 shr(int x, int y, int z) { - return at(this.getX() >> x, this.getY() >> y, this.getZ() >> z); + return at(this.x() >> x, this.y() >> y, this.z() >> z); } //FAWE end @@ -491,7 +530,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 shl(int x, int y, int z) { - return at(this.getX() << x, this.getY() << y, this.getZ() << z); + return at(this.x() << x, this.y() << y, this.z() << z); } //FAWE end @@ -521,7 +560,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public int lengthSq() { - return getX() * getX() + getY() * getY() + getZ() * getZ(); + return x() * x() + y() * y() + z() * z(); } //FAWE end @@ -543,9 +582,9 @@ public abstract class BlockVector3 { */ //FAWE start - getter public int distanceSq(BlockVector3 other) { - int dx = other.getX() - getX(); - int dy = other.getY() - getY(); - int dz = other.getZ() - getZ(); + int dx = other.x() - x(); + int dy = other.y() - y(); + int dz = other.z() - z(); return dx * dx + dy * dy + dz * dz; } //FAWE end @@ -559,9 +598,9 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 normalize() { double len = length(); - double x = this.getX() / len; - double y = this.getY() / len; - double z = this.getZ() / len; + double x = this.x() / len; + double y = this.y() / len; + double z = this.z() / len; return BlockVector3.at(x, y, z); } //FAWE end @@ -574,7 +613,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public double dot(BlockVector3 other) { - return getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ(); + return x() * other.x() + y() * other.y() + z() * other.z(); } //FAWE end @@ -587,9 +626,9 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 cross(BlockVector3 other) { return new BlockVector3Imp( - getY() * other.getZ() - getZ() * other.getY(), - getZ() * other.getX() - getX() * other.getZ(), - getX() * other.getY() - getY() * other.getX() + y() * other.z() - z() * other.y(), + z() * other.x() - x() * other.z(), + x() * other.y() - y() * other.x() ); } //FAWE end @@ -603,8 +642,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public boolean containedWithin(BlockVector3 min, BlockVector3 max) { - return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max - .getY() && getZ() >= min.getZ() && getZ() <= max.getZ(); + return x() >= min.x() && x() <= max.x() && y() >= min.y() && y() <= max.y() && z() >= min.z() && z() <= max.z(); } //FAWE end @@ -618,11 +656,11 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 clampY(int min, int max) { checkArgument(min <= max, "minimum cannot be greater than maximum"); - if (getY() < min) { - return BlockVector3.at(getX(), min, getZ()); + if (y() < min) { + return BlockVector3.at(x(), min, z()); } - if (getY() > max) { - return BlockVector3.at(getX(), max, getZ()); + if (y() > max) { + return BlockVector3.at(x(), max, z()); } return this; } @@ -668,7 +706,7 @@ public abstract class BlockVector3 { */ //FAWE start - getter public BlockVector3 abs() { - return BlockVector3.at(Math.abs(getX()), Math.abs(getY()), Math.abs(getZ())); + return BlockVector3.at(Math.abs(x()), Math.abs(y()), Math.abs(z())); } //FAWE end @@ -686,8 +724,8 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) { angle = Math.toRadians(angle); - double x = this.getX() - aboutX; - double z = this.getZ() - aboutZ; + double x = this.x() - aboutX; + double z = this.z() - aboutZ; double cos = Math.cos(angle); double sin = Math.sin(angle); double x2 = x * cos - z * sin; @@ -695,7 +733,7 @@ public abstract class BlockVector3 { return BlockVector3.at( x2 + aboutX + translateX, - getY(), + y(), z2 + aboutZ + translateZ ); } @@ -707,16 +745,16 @@ public abstract class BlockVector3 { * @return pitch in radians */ public double toPitch() { - double x = getX(); - double z = getZ(); + double x = x(); + double z = z(); if (x == 0 && z == 0) { - return getY() > 0 ? -90 : 90; + return y() > 0 ? -90 : 90; } else { double x2 = x * x; double z2 = z * z; double xz = Math.sqrt(x2 + z2); - return Math.toDegrees(Math.atan(-getY() / xz)); + return Math.toDegrees(Math.atan(-y() / xz)); } } @@ -726,8 +764,8 @@ public abstract class BlockVector3 { * @return yaw in radians */ public double toYaw() { - double x = getX(); - double z = getZ(); + double x = x(); + double z = z(); double t = Math.atan2(-x, z); double tau = 2 * Math.PI; @@ -744,9 +782,9 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 getMinimum(BlockVector3 v2) { return new BlockVector3Imp( - Math.min(getX(), v2.getX()), - Math.min(getY(), v2.getY()), - Math.min(getZ(), v2.getZ()) + Math.min(x(), v2.x()), + Math.min(y(), v2.y()), + Math.min(z(), v2.z()) ); } //FAWE end @@ -760,9 +798,9 @@ public abstract class BlockVector3 { //FAWE start - getter public BlockVector3 getMaximum(BlockVector3 v2) { return new BlockVector3Imp( - Math.max(getX(), v2.getX()), - Math.max(getY(), v2.getY()), - Math.max(getZ(), v2.getZ()) + Math.max(x(), v2.x()), + Math.max(y(), v2.y()), + Math.max(z(), v2.z()) ); } //FAWE end @@ -814,20 +852,21 @@ public abstract class BlockVector3 { return orDefault.getBiome(this); } + @Deprecated(forRemoval = true, since = "2.11.2") public CompoundTag getNbtData(Extent orDefault) { - return orDefault.getFullBlock(getX(), getY(), getZ()).getNbtData(); + return orDefault.getFullBlock(x(), y(), z()).getNbtData(); } public BlockState getOrdinalBelow(Extent orDefault) { - return orDefault.getBlock(getX(), getY() - 1, getZ()); + return orDefault.getBlock(x(), y() - 1, z()); } public BlockState getStateAbove(Extent orDefault) { - return orDefault.getBlock(getX(), getY() + 1, getZ()); + return orDefault.getBlock(x(), y() + 1, z()); } public BlockState getStateRelativeY(Extent orDefault, final int y) { - return orDefault.getBlock(getX(), getY() + y, getZ()); + return orDefault.getBlock(x(), y() + y, z()); } /** @@ -836,21 +875,21 @@ public abstract class BlockVector3 { * @return a new {@link BlockVector2} */ public BlockVector2 toBlockVector2() { - return BlockVector2.at(getX(), getZ()); + return BlockVector2.at(x(), z()); } public Vector3 toVector3() { - return Vector3.at(getX(), getY(), getZ()); + return Vector3.at(x(), y(), z()); } + //FAWE start - not a record, need own implementations @Override public boolean equals(Object obj) { - if (!(obj instanceof BlockVector3)) { + if (!(obj instanceof final BlockVector3 other)) { return false; } - BlockVector3 other = (BlockVector3) obj; - return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ(); + return other.x() == this.x() && other.y() == this.y() && other.z() == this.z(); } public final boolean equals(BlockVector3 other) { @@ -858,17 +897,18 @@ public abstract class BlockVector3 { return false; } - return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ(); + return other.x() == this.x() && other.y() == this.y() && other.z() == this.z(); } @Override public int hashCode() { - return (getX() ^ (getZ() << 12)) ^ (getY() << 24); + return (x() ^ (z() << 12)) ^ (y() << 24); } + //FAWE end @Override public String toString() { - return "(" + getX() + ", " + getY() + ", " + getZ() + ")"; + return "(" + x() + ", " + y() + ", " + z() + ")"; } /** @@ -877,7 +917,7 @@ public abstract class BlockVector3 { * @return string */ public String toParserString() { - return getX() + "," + getY() + "," + getZ(); + return x() + "," + y() + "," + z(); } //Used by VS fork diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3Imp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3Imp.java index ab202e83b..5ec2f4fe2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3Imp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3Imp.java @@ -56,33 +56,33 @@ public final class BlockVector3Imp extends BlockVector3 { } @Override - public final int getX() { + public int x() { return x; } @Override - public final int getY() { + public int y() { return y; } @Override - public final int getZ() { + public int z() { return z; } @Override public int hashCode() { - return (getX() ^ (getZ() << 12)) ^ (getY() << 24); + return (x() ^ (z() << 12)) ^ (y() << 24); } @Override - public final BlockVector3 toImmutable() { + public BlockVector3 toImmutable() { return this; } @Override public String toString() { - return "(" + getX() + ", " + getY() + ", " + getZ() + ")"; + return "(" + x() + ", " + y() + ", " + z() + ")"; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector2.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector2.java index d680b0c0d..089ed62ca 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector2.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector2.java @@ -19,12 +19,13 @@ package com.sk89q.worldedit.math; +import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.worldedit.math.transform.AffineTransform; /** * An immutable 2-dimensional vector. */ -public final class Vector2 { +public record Vector2(double x, double z) { public static final Vector2 ZERO = new Vector2(0, 0); public static final Vector2 UNIT_X = new Vector2(1, 0); @@ -50,29 +51,27 @@ public final class Vector2 { return new Vector2(x, z); } - private final double x; - private final double z; - - /** - * Construct an instance. - * - * @param x the X coordinate - * @param z the Z coordinate - */ - private Vector2(double x, double z) { - this.x = x; - this.z = z; - } - /** * Get the X coordinate. * * @return the x coordinate + * @deprecated use {@link #x()} instead */ + @Deprecated(forRemoval = true, since = "2.11.0") public double getX() { return x; } + /** + * Get the X coordinate, aligned to the block grid. + * + * @return the block-aligned x coordinate + * @since 2.11.0 + */ + public int blockX() { + return MathMan.roundInt(x); + } + /** * Set the X coordinate. * @@ -83,11 +82,23 @@ public final class Vector2 { return Vector2.at(x, z); } + /** + * Get the Z coordinate, aligned to the block grid. + * + * @return the block-aligned z coordinate + * @since 2.11.0 + */ + public int blockZ() { + return MathMan.roundInt(z); + } + /** * Get the Z coordinate. * * @return the z coordinate + * @deprecated use {@link #z()} instead */ + @Deprecated(forRemoval = true, since = "2.11.0") public double getZ() { return z; } @@ -458,24 +469,6 @@ public final class Vector2 { return Vector3.at(x, y, z); } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Vector2)) { - return false; - } - - Vector2 other = (Vector2) obj; - return other.x == this.x && other.z == this.z; - - } - - @Override - public int hashCode() { - //FAWE start - XOR over x z calc - return (int) x << 16 ^ (int) z; - //FAWE end - } - @Override public String toString() { return "(" + x + ", " + z + ")"; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java index 5a4d550b4..3b359920b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java @@ -32,7 +32,9 @@ import static com.google.common.base.Preconditions.checkArgument; /** * An immutable 3-dimensional vector. */ +//FAWE start - not a record, make abstract public abstract class Vector3 { +//FAWE end public static final Vector3 ZERO = Vector3.at(0, 0, 0); public static final Vector3 UNIT_X = Vector3.at(1, 0, 0); @@ -69,9 +71,9 @@ public abstract class Vector3 { private static final Comparator YZX_ORDER = (a, b) -> { return ComparisonChain.start() - .compare(a.getY(), b.getY()) - .compare(a.getZ(), b.getZ()) - .compare(a.getX(), b.getX()) + .compare(a.y(), b.y()) + .compare(a.z(), b.z()) + .compare(a.x(), b.x()) .result(); }; @@ -96,7 +98,7 @@ public abstract class Vector3 { * @return the x coordinate */ public int getBlockX() { - return MathMan.roundInt(getX()); + return MathMan.roundInt(x()); } /** @@ -105,7 +107,7 @@ public abstract class Vector3 { * @return the y coordinate */ public int getBlockY() { - return MathMan.roundInt(getY()); + return MathMan.roundInt(y()); } /** @@ -114,7 +116,7 @@ public abstract class Vector3 { * @return the z coordinate */ public int getBlockZ() { - return MathMan.roundInt(getZ()); + return MathMan.roundInt(z()); } public MutableVector3 setComponents(Vector3 other) { @@ -130,27 +132,27 @@ public abstract class Vector3 { } public MutableVector3 mutX(int x) { - return new MutableVector3(x, getY(), getZ()); + return new MutableVector3(x, y(), z()); } public MutableVector3 mutX(double x) { - return new MutableVector3(x, getY(), getZ()); + return new MutableVector3(x, y(), z()); } public MutableVector3 mutY(int y) { - return new MutableVector3(getX(), y, getZ()); + return new MutableVector3(x(), y, z()); } public MutableVector3 mutY(double y) { - return new MutableVector3(getX(), y, getZ()); + return new MutableVector3(x(), y, z()); } public MutableVector3 mutZ(int z) { - return new MutableVector3(getX(), getY(), z); + return new MutableVector3(x(), y(), z); } public MutableVector3 mutZ(double z) { - return new MutableVector3(getX(), getY(), z); + return new MutableVector3(x(), y(), z); } //FAWE end @@ -158,10 +160,29 @@ public abstract class Vector3 { * Get the X coordinate. * * @return the x coordinate + * @since 2.11.0 */ - //FAWE start - made abstract - public abstract double getX(); - //FAWE end + public abstract double x(); + + /** + * Get the X coordinate, aligned to the block grid. + * + * @return the block-aligned x coordinate + */ + public int blockX() { + return MathMan.roundInt(this.x()); + } + + /** + * Get the X coordinate. + * + * @return the x coordinate + * @deprecated use {@link #x()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") + public double getX() { + return this.x(); + } /** * Set the X coordinate. @@ -171,18 +192,38 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 withX(double x) { - return Vector3.at(x, getY(), getZ()); + return Vector3.at(x, y(), z()); } //FAWE end + /** * Get the Y coordinate. * * @return the y coordinate + * @since 2.11.0 */ - //FAWE start - made abstract - public abstract double getY(); - //FAWE end + public abstract double y(); + + /** + * Get the Y coordinate, aligned to the block grid. + * + * @return the block-aligned y coordinate + */ + public int blockY() { + return MathMan.roundInt(this.y()); + } + + /** + * Get the Y coordinate. + * + * @return the y coordinate + * @deprecated use {@link #y()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") + public double getY() { + return this.y(); + } /** * Set the Y coordinate. @@ -192,7 +233,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 withY(double y) { - return Vector3.at(getX(), y, getZ()); + return Vector3.at(x(), y, z()); } //FAWE end @@ -200,10 +241,29 @@ public abstract class Vector3 { * Get the Z coordinate. * * @return the z coordinate + * @since 2.11.0 */ - //FAWE start - made abstract - public abstract double getZ(); - //FAWE end + public abstract double z(); + + /** + * Get the Z coordinate, aligned to the block grid. + * + * @return the block-aligned z coordinate + */ + public int blockZ() { + return MathMan.roundInt(this.z()); + } + + /** + * Get the Z coordinate. + * + * @return the z coordinate + * @deprecated use {@link #z()} instead + */ + @Deprecated(forRemoval = true, since = "2.11.0") + public double getZ() { + return this.z(); + } /** * Set the Z coordinate. @@ -213,7 +273,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 withZ(double z) { - return Vector3.at(getX(), getY(), z); + return Vector3.at(x(), y(), z); } //FAWE end @@ -225,7 +285,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 add(Vector3 other) { - return add(other.getX(), other.getY(), other.getZ()); + return add(other.x(), other.y(), other.z()); } //FAWE end @@ -239,7 +299,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 add(double x, double y, double z) { - return Vector3.at(this.getX() + x, this.getY() + y, this.getZ() + z); + return Vector3.at(this.x() + x, this.y() + y, this.z() + z); } //FAWE end @@ -252,14 +312,14 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 add(Vector3... others) { - double newX = getX(); - double newY = getY(); - double newZ = getZ(); + double newX = x(); + double newY = y(); + double newZ = z(); for (Vector3 other : others) { - newX += other.getX(); - newY += other.getY(); - newZ += other.getZ(); + newX += other.x(); + newY += other.y(); + newZ += other.z(); } return Vector3.at(newX, newY, newZ); @@ -275,7 +335,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 subtract(Vector3 other) { - return subtract(other.getX(), other.getY(), other.getZ()); + return subtract(other.x(), other.y(), other.z()); } //FAWE end @@ -290,7 +350,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 subtract(double x, double y, double z) { - return Vector3.at(this.getX() - x, this.getY() - y, this.getZ() - z); + return Vector3.at(this.x() - x, this.y() - y, this.z() - z); } //FAWE end @@ -303,14 +363,14 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 subtract(Vector3... others) { - double newX = getX(); - double newY = getY(); - double newZ = getZ(); + double newX = x(); + double newY = y(); + double newZ = z(); for (Vector3 other : others) { - newX -= other.getX(); - newY -= other.getY(); - newZ -= other.getZ(); + newX -= other.x(); + newY -= other.y(); + newZ -= other.z(); } return Vector3.at(newX, newY, newZ); @@ -325,7 +385,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 multiply(Vector3 other) { - return multiply(other.getX(), other.getY(), other.getZ()); + return multiply(other.x(), other.y(), other.z()); } //FAWE end @@ -339,7 +399,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 multiply(double x, double y, double z) { - return Vector3.at(this.getX() * x, this.getY() * y, this.getZ() * z); + return Vector3.at(this.x() * x, this.y() * y, this.z() * z); } //FAWE end @@ -351,14 +411,14 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 multiply(Vector3... others) { - double newX = getX(); - double newY = getY(); - double newZ = getZ(); + double newX = x(); + double newY = y(); + double newZ = z(); for (Vector3 other : others) { - newX *= other.getX(); - newY *= other.getY(); - newZ *= other.getZ(); + newX *= other.x(); + newY *= other.y(); + newZ *= other.z(); } return Vector3.at(newX, newY, newZ); @@ -383,7 +443,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 divide(Vector3 other) { - return divide(other.getX(), other.getY(), other.getZ()); + return divide(other.x(), other.y(), other.z()); } //FAWE end @@ -397,7 +457,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 divide(double x, double y, double z) { - return Vector3.at(this.getX() / x, this.getY() / y, this.getZ() / z); + return Vector3.at(this.x() / x, this.y() / y, this.z() / z); } //FAWE end @@ -427,7 +487,7 @@ public abstract class Vector3 { */ //FAWE start - getter public double lengthSq() { - return getX() * getX() + getY() * getY() + getZ() * getZ(); + return x() * x() + y() * y() + z() * z(); } //FAWE end @@ -449,9 +509,9 @@ public abstract class Vector3 { */ //FAWE start - getter public double distanceSq(Vector3 other) { - double dx = other.getX() - getX(); - double dy = other.getY() - getY(); - double dz = other.getZ() - getZ(); + double dx = other.x() - x(); + double dy = other.y() - y(); + double dz = other.z() - z(); return dx * dx + dy * dy + dz * dz; } //FAWE end @@ -474,7 +534,7 @@ public abstract class Vector3 { */ //FAWE start - getter public double dot(Vector3 other) { - return getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ(); + return x() * other.x() + y() * other.y() + z() * other.z(); } //FAWE end @@ -487,9 +547,9 @@ public abstract class Vector3 { //FAWE start - getter public Vector3 cross(Vector3 other) { return Vector3.at( - getY() * other.getZ() - getZ() * other.getY(), - getZ() * other.getX() - getX() * other.getZ(), - getX() * other.getY() - getY() * other.getX() + y() * other.z() - z() * other.y(), + z() * other.x() - x() * other.z(), + x() * other.y() - y() * other.x() ); } //FAWE end @@ -503,8 +563,7 @@ public abstract class Vector3 { */ //FAWE start - getter public boolean containedWithin(Vector3 min, Vector3 max) { - return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max.getY() && getZ() >= min.getZ() && getZ() <= max - .getZ(); + return x() >= min.x() && x() <= max.x() && y() >= min.y() && y() <= max.y() && z() >= min.z() && z() <= max.z(); } //FAWE end @@ -518,11 +577,11 @@ public abstract class Vector3 { //FAWE start - getter public Vector3 clampY(int min, int max) { checkArgument(min <= max, "minimum cannot be greater than maximum"); - if (getY() < min) { - return Vector3.at(getX(), min, getZ()); + if (y() < min) { + return Vector3.at(x(), min, z()); } - if (getY() > max) { - return Vector3.at(getX(), max, getZ()); + if (y() > max) { + return Vector3.at(x(), max, z()); } return this; } @@ -535,7 +594,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 floor() { - return Vector3.at(Math.floor(getX()), Math.floor(getY()), Math.floor(getZ())); + return Vector3.at(Math.floor(x()), Math.floor(y()), Math.floor(z())); } //FAWE end @@ -546,7 +605,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 ceil() { - return Vector3.at(Math.ceil(getX()), Math.ceil(getY()), Math.ceil(getZ())); + return Vector3.at(Math.ceil(x()), Math.ceil(y()), Math.ceil(z())); } //FAWE end @@ -559,7 +618,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 round() { - return Vector3.at(Math.floor(getX() + 0.5), Math.floor(getY() + 0.5), Math.floor(getZ() + 0.5)); + return Vector3.at(Math.floor(x() + 0.5), Math.floor(y() + 0.5), Math.floor(z() + 0.5)); } //FAWE end @@ -570,7 +629,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 roundHalfUp() { - return Vector3.at(MathUtils.roundHalfUp(getX()), MathUtils.roundHalfUp(getY()), MathUtils.roundHalfUp(getZ())); + return Vector3.at(MathUtils.roundHalfUp(x()), MathUtils.roundHalfUp(y()), MathUtils.roundHalfUp(z())); } //FAWE end @@ -582,7 +641,7 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector3 abs() { - return Vector3.at(Math.abs(getX()), Math.abs(getY()), Math.abs(getZ())); + return Vector3.at(Math.abs(x()), Math.abs(y()), Math.abs(z())); } //FAWE end @@ -600,8 +659,8 @@ public abstract class Vector3 { //FAWE start - getter public Vector3 transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) { angle = Math.toRadians(angle); - double x = this.getX() - aboutX; - double z = this.getZ() - aboutZ; + double x = this.x() - aboutX; + double z = this.z() - aboutZ; double cos = Math.cos(angle); double sin = Math.sin(angle); double x2 = x * cos - z * sin; @@ -609,7 +668,7 @@ public abstract class Vector3 { return Vector3.at( x2 + aboutX + translateX, - getY(), + y(), z2 + aboutZ + translateZ ); } @@ -621,16 +680,16 @@ public abstract class Vector3 { * @return pitch in radians */ public double toPitch() { - double x = getX(); - double z = getZ(); + double x = x(); + double z = z(); if (x == 0 && z == 0) { - return getY() > 0 ? -90 : 90; + return y() > 0 ? -90 : 90; } else { double x2 = x * x; double z2 = z * z; double xz = Math.sqrt(x2 + z2); - return Math.toDegrees(Math.atan(-getY() / xz)); + return Math.toDegrees(Math.atan(-y() / xz)); } } @@ -640,8 +699,8 @@ public abstract class Vector3 { * @return yaw in radians */ public double toYaw() { - double x = getX(); - double z = getZ(); + double x = x(); + double z = z(); double t = Math.atan2(-x, z); double tau = 2 * Math.PI; @@ -658,9 +717,9 @@ public abstract class Vector3 { //FAWE start - getter public Vector3 getMinimum(Vector3 v2) { return Vector3.at( - Math.min(getX(), v2.getX()), - Math.min(getY(), v2.getY()), - Math.min(getZ(), v2.getZ()) + Math.min(x(), v2.x()), + Math.min(y(), v2.y()), + Math.min(z(), v2.z()) ); } //FAWE end @@ -674,9 +733,9 @@ public abstract class Vector3 { //FAWE start - getter public Vector3 getMaximum(Vector3 v2) { return Vector3.at( - Math.max(getX(), v2.getX()), - Math.max(getY(), v2.getY()), - Math.max(getZ(), v2.getZ()) + Math.max(x(), v2.x()), + Math.max(y(), v2.y()), + Math.max(z(), v2.z()) ); } //FAWE end @@ -700,7 +759,7 @@ public abstract class Vector3 { */ //FAWE start - getter public BlockVector3 toBlockPoint() { - return toBlockPoint(getX(), getY(), getZ()); + return toBlockPoint(x(), y(), z()); } //FAWE end @@ -711,24 +770,20 @@ public abstract class Vector3 { */ //FAWE start - getter public Vector2 toVector2() { - return Vector2.at(getX(), getZ()); + return Vector2.at(x(), z()); } //FAWE end + //FAWE start - not a record, need own implementations @Override public boolean equals(Object obj) { - if (!(obj instanceof Vector3)) { + if (!(obj instanceof final Vector3 other)) { return false; } - Vector3 other = (Vector3) obj; - //FAWE start - getter - return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ(); - //FAWE end + return other.x() == this.x() && other.y() == this.y() && other.z() == this.z(); } - //FAWE start - /** * Tests if vectors are equal, accounting for floating point errors * @@ -741,28 +796,27 @@ public abstract class Vector3 { } // Minecraft deals in whole blocks, thus any difference smaller than this is unnecessary - if (Math.abs(getX() - other.getX()) > 0.000001d) { + if (Math.abs(x() - other.x()) > 0.000001d) { return false; } - if (Math.abs(getY() - other.getY()) > 0.000001d) { + if (Math.abs(y() - other.y()) > 0.000001d) { return false; } - return !(Math.abs(getZ() - other.getZ()) > 0.000001d); + return !(Math.abs(z() - other.z()) > 0.000001d); + } + + @Override + public int hashCode() { + return (int) x() ^ (int) z() << 12 ^ (int) y() << 24; } //FAWE end - @Override - //FAWE start - XOR over get calculating all values independently - public int hashCode() { - return (int) getX() ^ (int) getZ() << 12 ^ (int) getY() << 24; - } - @Override public String toString() { //FAWE start - getter & ternary - String x = (getX() == getBlockX() ? "" + getBlockX() : "" + getX()); - String y = (getY() == getBlockY() ? "" + getBlockY() : "" + getY()); - String z = (getZ() == getBlockZ() ? "" + getBlockZ() : "" + getZ()); + String x = (x() == blockX() ? "" + blockX() : "" + x()); + String y = (y() == blockY() ? "" + blockY() : "" + y()); + String z = (z() == blockZ() ? "" + blockZ() : "" + z()); //FAWE end return "(" + x + ", " + y + ", " + z + ")"; } @@ -774,7 +828,7 @@ public abstract class Vector3 { */ //FAWE start - getter public String toParserString() { - return getX() + "," + getY() + "," + getZ(); + return x() + "," + y() + "," + z(); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java index 68e62e937..0eeabee70 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java @@ -89,10 +89,10 @@ public class HeightMap { this.maxSessionY = session.getMaxY(); //FAWE end - int minX = region.getMinimumPoint().getBlockX(); - int minY = region.getMinimumPoint().getBlockY(); - int minZ = region.getMinimumPoint().getBlockZ(); - int maxY = region.getMaximumPoint().getBlockY(); + int minX = region.getMinimumPoint().x(); + int minY = region.getMinimumPoint().y(); + int minZ = region.getMinimumPoint().z(); + int maxY = region.getMaximumPoint().y(); // Store current heightmap data data = new int[width * height]; @@ -100,14 +100,14 @@ public class HeightMap { //FAWE start if (layers) { BlockVector3 min = region.getMinimumPoint(); - int bx = min.getBlockX(); - int bz = min.getBlockZ(); + int bx = min.x(); + int bz = min.z(); Iterator flat = Regions.asFlatRegion(region).asFlatRegion().iterator(); int layer = session.getMinY(); while (flat.hasNext()) { BlockVector2 pos = flat.next(); - int x = pos.getBlockX(); - int z = pos.getBlockZ(); + int x = pos.x(); + int z = pos.z(); layer = session.getNearestSurfaceLayer(x, z, (layer + 7) >> 3, session.getMinY(), maxY); data[(z - bz) * width + (x - bx)] = layer; } @@ -169,10 +169,10 @@ public class HeightMap { checkNotNull(data); BlockVector3 min = region.getMinimumPoint(); - int originX = min.getBlockX(); - int originZ = min.getBlockZ(); + int originX = min.x(); + int originZ = min.z(); - int maxY = region.getMaximumPoint().getBlockY(); + int maxY = region.getMaximumPoint().y(); BlockState fillerAir = BlockTypes.AIR.getDefaultState(); @@ -261,11 +261,11 @@ public class HeightMap { checkNotNull(data); BlockVector3 min = region.getMinimumPoint(); - int originX = min.getBlockX(); - int originY = min.getBlockY(); - int originZ = min.getBlockZ(); + int originX = min.x(); + int originY = min.y(); + int originZ = min.z(); - int maxY = region.getMaximumPoint().getBlockY(); + int maxY = region.getMaximumPoint().y(); BlockState fillerAir = BlockTypes.AIR.getDefaultState(); int blocksChanged = 0; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/SnowHeightMap.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/SnowHeightMap.java index 97f58f9e1..0c12c4652 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/SnowHeightMap.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/SnowHeightMap.java @@ -65,10 +65,10 @@ public class SnowHeightMap { this.width = region.getWidth(); this.height = region.getLength(); - int minX = region.getMinimumPoint().getBlockX(); - int minY = region.getMinimumPoint().getBlockY(); - int minZ = region.getMinimumPoint().getBlockZ(); - int maxY = region.getMaximumPoint().getBlockY(); + int minX = region.getMinimumPoint().x(); + int minY = region.getMinimumPoint().y(); + int minZ = region.getMinimumPoint().z(); + int maxY = region.getMaximumPoint().y(); // Store current heightmap data data = new float[width * height]; @@ -134,11 +134,11 @@ public class SnowHeightMap { checkNotNull(data); BlockVector3 minY = region.getMinimumPoint(); - int originX = minY.getBlockX(); - int originY = minY.getBlockY(); - int originZ = minY.getBlockZ(); + int originX = minY.x(); + int originY = minY.y(); + int originZ = minY.z(); - int maxY = region.getMaximumPoint().getBlockY(); + int maxY = region.getMaximumPoint().y(); BlockState fillerAir = BlockTypes.AIR.getDefaultState(); BlockState fillerSnow = BlockTypes.SNOW_BLOCK.getDefaultState(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java index 561ba14bf..0ecced12e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java @@ -164,10 +164,10 @@ public class KochanekBartelsInterpolation implements Interpolation { //FAWE start double r2 = remainder * remainder; double r3 = r2 * remainder; - mutable.mutX((a.getX() * r3 + b.getX() * r2 + c.getX() * remainder + d.getX())); - mutable.mutY((a.getY() * r3 + b.getY() * r2 + c.getY() * remainder + d.getY())); - mutable.mutZ((a.getZ() * r3 + b.getZ() * r2 + c.getZ() * remainder + d.getZ())); - return Vector3.at(mutable.getX(), mutable.getY(), mutable.getZ()); + mutable.mutX((a.x() * r3 + b.x() * r2 + c.x() * remainder + d.x())); + mutable.mutY((a.y() * r3 + b.y() * r2 + c.y() * remainder + d.y())); + mutable.mutZ((a.z() * r3 + b.z() * r2 + c.z() * remainder + d.z())); + return Vector3.at(mutable.x(), mutable.y(), mutable.z()); //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/noise/JLibNoiseGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/noise/JLibNoiseGenerator.java index a7f3fe449..c541d2d3d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/noise/JLibNoiseGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/noise/JLibNoiseGenerator.java @@ -47,12 +47,12 @@ abstract class JLibNoiseGenerator implements NoiseGenerator { @Override public float noise(Vector2 position) { - return forceRange(module.GetValue(position.getX(), 0, position.getZ())); + return forceRange(module.GetValue(position.x(), 0, position.z())); } @Override public float noise(Vector3 position) { - return forceRange(module.GetValue(position.getX(), position.getY(), position.getZ())); + return forceRange(module.GetValue(position.x(), position.y(), position.z())); } private float forceRange(double value) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java index c06e0968e..92e81eea2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java @@ -195,6 +195,33 @@ public class AffineTransform implements Transform, Serializable { // =================================================================== // general methods + /** + * Returns the affine transform created by applying first the affine + * transform given by the parameters, then this affine transform. + * + * @return the composition this * that + */ + public AffineTransform concatenate(double o00, double o01, double o02, double o03, + double o10, double o11, double o12, double o13, + double o20, double o21, double o22, double o23) { + double n00 = m00 * o00 + m01 * o10 + m02 * o20; + double n01 = m00 * o01 + m01 * o11 + m02 * o21; + double n02 = m00 * o02 + m01 * o12 + m02 * o22; + double n03 = m00 * o03 + m01 * o13 + m02 * o23 + m03; + double n10 = m10 * o00 + m11 * o10 + m12 * o20; + double n11 = m10 * o01 + m11 * o11 + m12 * o21; + double n12 = m10 * o02 + m11 * o12 + m12 * o22; + double n13 = m10 * o03 + m11 * o13 + m12 * o23 + m13; + double n20 = m20 * o00 + m21 * o10 + m22 * o20; + double n21 = m20 * o01 + m21 * o11 + m22 * o21; + double n22 = m20 * o02 + m21 * o12 + m22 * o22; + double n23 = m20 * o03 + m21 * o13 + m22 * o23 + m23; + return new AffineTransform( + n00, n01, n02, n03, + n10, n11, n12, n13, + n20, n21, n22, n23); + } + /** * Returns the affine transform created by applying first the affine * transform given by {@code that}, then this affine transform. @@ -203,22 +230,10 @@ public class AffineTransform implements Transform, Serializable { * @return the composition this * that */ public AffineTransform concatenate(AffineTransform that) { - double n00 = m00 * that.m00 + m01 * that.m10 + m02 * that.m20; - double n01 = m00 * that.m01 + m01 * that.m11 + m02 * that.m21; - double n02 = m00 * that.m02 + m01 * that.m12 + m02 * that.m22; - double n03 = m00 * that.m03 + m01 * that.m13 + m02 * that.m23 + m03; - double n10 = m10 * that.m00 + m11 * that.m10 + m12 * that.m20; - double n11 = m10 * that.m01 + m11 * that.m11 + m12 * that.m21; - double n12 = m10 * that.m02 + m11 * that.m12 + m12 * that.m22; - double n13 = m10 * that.m03 + m11 * that.m13 + m12 * that.m23 + m13; - double n20 = m20 * that.m00 + m21 * that.m10 + m22 * that.m20; - double n21 = m20 * that.m01 + m21 * that.m11 + m22 * that.m21; - double n22 = m20 * that.m02 + m21 * that.m12 + m22 * that.m22; - double n23 = m20 * that.m03 + m21 * that.m13 + m22 * that.m23 + m23; - return new AffineTransform( - n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23 + return concatenate( + that.m00, that.m01, that.m02, that.m03, + that.m10, that.m11, that.m12, that.m13, + that.m20, that.m21, that.m22, that.m23 ); } @@ -250,48 +265,45 @@ public class AffineTransform implements Transform, Serializable { } public AffineTransform translate(Vector3 vec) { - return translate(vec.getX(), vec.getY(), vec.getZ()); + return translate(vec.x(), vec.y(), vec.z()); } public AffineTransform translate(BlockVector3 vec) { - return translate(vec.getX(), vec.getY(), vec.getZ()); + return translate(vec.x(), vec.y(), vec.z()); } public AffineTransform translate(double x, double y, double z) { - return concatenate(new AffineTransform(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z)); + return concatenate(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z); } public AffineTransform rotateX(double theta) { double cot = MathUtils.dCos(theta); double sit = MathUtils.dSin(theta); return concatenate( - new AffineTransform( - 1, 0, 0, 0, - 0, cot, -sit, 0, - 0, sit, cot, 0 - )); + 1, 0, 0, 0, + 0, cot, -sit, 0, + 0, sit, cot, 0 + ); } public AffineTransform rotateY(double theta) { double cot = MathUtils.dCos(theta); double sit = MathUtils.dSin(theta); return concatenate( - new AffineTransform( - cot, 0, sit, 0, - 0, 1, 0, 0, - -sit, 0, cot, 0 - )); + cot, 0, sit, 0, + 0, 1, 0, 0, + -sit, 0, cot, 0 + ); } public AffineTransform rotateZ(double theta) { double cot = MathUtils.dCos(theta); double sit = MathUtils.dSin(theta); return concatenate( - new AffineTransform( - cot, -sit, 0, 0, - sit, cot, 0, 0, - 0, 0, 1, 0 - )); + cot, -sit, 0, 0, + sit, cot, 0, 0, + 0, 0, 1, 0 + ); } public AffineTransform scale(double s) { @@ -299,33 +311,33 @@ public class AffineTransform implements Transform, Serializable { } public AffineTransform scale(double sx, double sy, double sz) { - return concatenate(new AffineTransform(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0)); + return concatenate(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0); } public AffineTransform scale(Vector3 vec) { - return scale(vec.getX(), vec.getY(), vec.getZ()); + return scale(vec.x(), vec.y(), vec.z()); } //FAWE start public boolean isScaled(Vector3 vector) { - boolean flip = vector.getX() != 0 && m00 < 0; - if (vector.getY() != 0 && m11 < 0) { + boolean flip = vector.x() != 0 && m00 < 0; + if (vector.y() != 0 && m11 < 0) { flip = !flip; } - if (vector.getZ() != 0 && m22 < 0) { + if (vector.z() != 0 && m22 < 0) { flip = !flip; } if (flip) { return true; } // Check for flip-and-rotate - if (vector.getX() != 0 && vector.getY() != 0 && ((m01 < 0 && m10 < 0) || (m01 > 0 && m10 > 0))) { + if (vector.x() != 0 && vector.y() != 0 && ((m01 < 0 && m10 < 0) || (m01 > 0 && m10 > 0))) { flip = true; } - if (vector.getX() != 0 && vector.getZ() != 0 && ((m02 < 0 && m20 < 0) || (m02 > 0 && m20 > 0))) { + if (vector.x() != 0 && vector.z() != 0 && ((m02 < 0 && m20 < 0) || (m02 > 0 && m20 > 0))) { flip = !flip; } - if (vector.getY() != 0 && vector.getZ() != 0 && ((m12 < 0 && m21 < 0) || (m12 > 0 && m21 > 0))) { + if (vector.y() != 0 && vector.z() != 0 && ((m12 < 0 && m21 < 0) || (m12 > 0 && m21 > 0))) { flip = !flip; } return flip; @@ -334,9 +346,9 @@ public class AffineTransform implements Transform, Serializable { @Override public Vector3 apply(Vector3 vector) { - double x = (vector.getX() * m00 + vector.getY() * m01 + vector.getZ() * m02 + m03); - double y = (vector.getX() * m10 + vector.getY() * m11 + vector.getZ() * m12 + m13); - double z = (vector.getX() * m20 + vector.getY() * m21 + vector.getZ() * m22 + m23); + double x = (vector.x() * m00 + vector.y() * m01 + vector.z() * m02 + m03); + double y = (vector.x() * m10 + vector.y() * m11 + vector.z() * m12 + m13); + double z = (vector.x() * m20 + vector.y() * m21 + vector.z() * m22 + m23); vector = vector.mutX(x); vector = vector.mutY(y); vector = vector.mutZ(z); @@ -352,9 +364,9 @@ public class AffineTransform implements Transform, Serializable { //FAWE start - check other identity if (other instanceof Identity || other.isIdentity()) { return this; - } else if (other instanceof AffineTransform) { + } else if (other instanceof AffineTransform otherTransform) { //FAWE end - return concatenate((AffineTransform) other); + return concatenate(otherTransform); } else { return new CombinedTransform(this, other); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractFlatRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractFlatRegion.java index 8534f0f35..a868e0262 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractFlatRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractFlatRegion.java @@ -29,12 +29,12 @@ public abstract class AbstractFlatRegion extends AbstractRegion implements FlatR @Override public int getMinimumY() { - return getMinimumPoint().getBlockY(); + return getMinimumPoint().y(); } @Override public int getMaximumY() { - return getMaximumPoint().getBlockY(); + return getMaximumPoint().y(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java index 85979b217..f87f9741b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java @@ -20,8 +20,6 @@ package com.sk89q.worldedit.regions; import com.fastasyncworldedit.core.math.BlockVectorSet; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; @@ -109,10 +107,10 @@ public abstract class AbstractRegion extends AbstractSet implement final List points = new ArrayList<>(4); - points.add(BlockVector2.at(min.getX(), min.getZ())); - points.add(BlockVector2.at(min.getX(), max.getZ())); - points.add(BlockVector2.at(max.getX(), max.getZ())); - points.add(BlockVector2.at(max.getX(), min.getZ())); + points.add(BlockVector2.at(min.x(), min.z())); + points.add(BlockVector2.at(min.x(), max.z())); + points.add(BlockVector2.at(max.x(), max.z())); + points.add(BlockVector2.at(max.x(), min.z())); return points; } @@ -122,9 +120,9 @@ public abstract class AbstractRegion extends AbstractSet implement BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return (max.getX() - min.getX() + 1L) - * (max.getY() - min.getY() + 1L) - * (max.getZ() - min.getZ() + 1L); + return (max.x() - min.x() + 1L) + * (max.y() - min.y() + 1L) + * (max.z() - min.z() + 1L); } /** @@ -137,7 +135,7 @@ public abstract class AbstractRegion extends AbstractSet implement BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return max.getX() - min.getX() + 1; + return max.x() - min.x() + 1; } /** @@ -150,7 +148,7 @@ public abstract class AbstractRegion extends AbstractSet implement BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return max.getY() - min.getY() + 1; + return max.y() - min.y() + 1; } /** @@ -163,7 +161,7 @@ public abstract class AbstractRegion extends AbstractSet implement BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return max.getZ() - min.getZ() + 1; + return max.z() - min.z() + 1; } /** @@ -179,12 +177,12 @@ public abstract class AbstractRegion extends AbstractSet implement final BlockVector3 maxBlock = getMaximumPoint(); //FAWE start - final BlockVector2 min = BlockVector2.at(minBlock.getX() >> 4, minBlock.getZ() >> 4); - final BlockVector2 max = BlockVector2.at(maxBlock.getX() >> 4, maxBlock.getZ() >> 4); + final BlockVector2 min = BlockVector2.at(minBlock.x() >> 4, minBlock.z() >> 4); + final BlockVector2 max = BlockVector2.at(maxBlock.x() >> 4, maxBlock.z() >> 4); //FAWE end - for (int X = min.getBlockX(); X <= max.getBlockX(); ++X) { - for (int Z = min.getBlockZ(); Z <= max.getBlockZ(); ++Z) { + for (int X = min.x(); X <= max.x(); ++X) { + for (int Z = min.z(); Z <= max.z(); ++Z) { if (containsChunk(X, Z)) { chunks.add(BlockVector2.at(X, Z)); } @@ -201,9 +199,9 @@ public abstract class AbstractRegion extends AbstractSet implement final BlockVector3 min = getMinimumPoint(); final BlockVector3 max = getMaximumPoint(); - for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) { - for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) { + for (int x = min.x(); x <= max.x(); ++x) { + for (int y = min.y(); y <= max.y(); ++y) { + for (int z = min.z(); z <= max.z(); ++z) { if (!contains(BlockVector3.at(x, y, z))) { continue; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index cc2f03aa2..4b0894d91 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.regions; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.math.BlockVectorSet; -import com.fastasyncworldedit.core.math.MutableBlockVector2; import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunk; @@ -161,12 +160,12 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { } pos1 = pos1.clampY(getWorldMinY(), getWorldMaxY()); pos2 = pos2.clampY(getWorldMinY(), getWorldMaxY()); - minX = Math.min(pos1.getX(), pos2.getX()); - minY = Math.min(pos1.getY(), pos2.getY()); - minZ = Math.min(pos1.getZ(), pos2.getZ()); - maxX = Math.max(pos1.getX(), pos2.getX()); - maxY = Math.max(pos1.getY(), pos2.getY()); - maxZ = Math.max(pos1.getZ(), pos2.getZ()); + minX = Math.min(pos1.x(), pos2.x()); + minY = Math.min(pos1.y(), pos2.y()); + minZ = Math.min(pos1.z(), pos2.z()); + maxX = Math.max(pos1.x(), pos2.x()); + maxY = Math.max(pos1.y(), pos2.y()); + maxZ = Math.max(pos1.z(), pos2.z()); } //FAWE start - allow region to be created without clamping Y @@ -177,12 +176,12 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { if (pos1 == null || pos2 == null) { return; } - minX = Math.min(pos1.getX(), pos2.getX()); - minY = Math.min(pos1.getY(), pos2.getY()); - minZ = Math.min(pos1.getZ(), pos2.getZ()); - maxX = Math.max(pos1.getX(), pos2.getX()); - maxY = Math.max(pos1.getY(), pos2.getY()); - maxZ = Math.max(pos1.getZ(), pos2.getZ()); + minX = Math.min(pos1.x(), pos2.x()); + minY = Math.min(pos1.y(), pos2.y()); + minZ = Math.min(pos1.z(), pos2.z()); + maxX = Math.max(pos1.x(), pos2.x()); + maxY = Math.max(pos1.y(), pos2.y()); + maxZ = Math.max(pos1.z(), pos2.z()); } //FAWE end @@ -197,16 +196,16 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return new RegionIntersection( // Project to Z-Y plane - new CuboidRegion(pos1.withX(min.getX()), pos2.withX(min.getX())), - new CuboidRegion(pos1.withX(max.getX()), pos2.withX(max.getX())), + new CuboidRegion(pos1.withX(min.x()), pos2.withX(min.x())), + new CuboidRegion(pos1.withX(max.x()), pos2.withX(max.x())), // Project to X-Y plane - new CuboidRegion(pos1.withZ(min.getZ()), pos2.withZ(min.getZ())), - new CuboidRegion(pos1.withZ(max.getZ()), pos2.withZ(max.getZ())), + new CuboidRegion(pos1.withZ(min.z()), pos2.withZ(min.z())), + new CuboidRegion(pos1.withZ(max.z()), pos2.withZ(max.z())), // Project to the X-Z plane - new CuboidRegion(pos1.withY(min.getY()), pos2.withY(min.getY())), - new CuboidRegion(pos1.withY(max.getY()), pos2.withY(max.getY())) + new CuboidRegion(pos1.withY(min.y()), pos2.withY(min.y())), + new CuboidRegion(pos1.withY(max.y()), pos2.withY(max.y())) ); } @@ -222,7 +221,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { BlockVector3 dimensions = getDimensions(); //FAWE start - if (dimensions.getX() <= 2 || dimensions.getZ() <= 2) { + if (dimensions.x() <= 2 || dimensions.z() <= 2) { // The wall are the region return new RegionIntersection(this); } @@ -230,18 +229,18 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return new RegionIntersection( // Project to Z-Y plane - new CuboidRegion(pos1.withX(min.getX()), pos2.withX(min.getX())), - new CuboidRegion(pos1.withX(max.getX()), pos2.withX(max.getX())), + new CuboidRegion(pos1.withX(min.x()), pos2.withX(min.x())), + new CuboidRegion(pos1.withX(max.x()), pos2.withX(max.x())), // Project to X-Y plane //FAWE start = prevent overlap new CuboidRegion( - pos1.withZ(min.getZ()).add(BlockVector3.UNIT_X), - pos2.withZ(min.getZ()).subtract(BlockVector3.UNIT_X) + pos1.withZ(min.z()).add(BlockVector3.UNIT_X), + pos2.withZ(min.z()).subtract(BlockVector3.UNIT_X) ), new CuboidRegion( - pos1.withZ(max.getZ()).add(BlockVector3.UNIT_X), - pos2.withZ(max.getZ()).subtract(BlockVector3.UNIT_X) + pos1.withZ(max.z()).add(BlockVector3.UNIT_X), + pos2.withZ(max.z()).subtract(BlockVector3.UNIT_X) ) //FAWE end ); @@ -277,45 +276,45 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { checkNotNull(changes); for (BlockVector3 change : changes) { - if (change.getX() > 0) { - if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) { - pos1 = pos1.add(change.getX(), 0, 0); + if (change.x() > 0) { + if (Math.max(pos1.x(), pos2.x()) == pos1.x()) { + pos1 = pos1.add(change.x(), 0, 0); } else { - pos2 = pos2.add(change.getX(), 0, 0); + pos2 = pos2.add(change.x(), 0, 0); } } else { - if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) { - pos1 = pos1.add(change.getX(), 0, 0); + if (Math.min(pos1.x(), pos2.x()) == pos1.x()) { + pos1 = pos1.add(change.x(), 0, 0); } else { - pos2 = pos2.add(change.getX(), 0, 0); + pos2 = pos2.add(change.x(), 0, 0); } } - if (change.getY() > 0) { - if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) { - pos1 = pos1.add(0, change.getY(), 0); + if (change.y() > 0) { + if (Math.max(pos1.y(), pos2.y()) == pos1.y()) { + pos1 = pos1.add(0, change.y(), 0); } else { - pos2 = pos2.add(0, change.getY(), 0); + pos2 = pos2.add(0, change.y(), 0); } } else { - if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) { - pos1 = pos1.add(0, change.getY(), 0); + if (Math.min(pos1.y(), pos2.y()) == pos1.y()) { + pos1 = pos1.add(0, change.y(), 0); } else { - pos2 = pos2.add(0, change.getY(), 0); + pos2 = pos2.add(0, change.y(), 0); } } - if (change.getZ() > 0) { - if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) { - pos1 = pos1.add(0, 0, change.getZ()); + if (change.z() > 0) { + if (Math.max(pos1.z(), pos2.z()) == pos1.z()) { + pos1 = pos1.add(0, 0, change.z()); } else { - pos2 = pos2.add(0, 0, change.getZ()); + pos2 = pos2.add(0, 0, change.z()); } } else { - if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) { - pos1 = pos1.add(0, 0, change.getZ()); + if (Math.min(pos1.z(), pos2.z()) == pos1.z()) { + pos1 = pos1.add(0, 0, change.z()); } else { - pos2 = pos2.add(0, 0, change.getZ()); + pos2 = pos2.add(0, 0, change.z()); } } } @@ -328,45 +327,45 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { checkNotNull(changes); for (BlockVector3 change : changes) { - if (change.getX() < 0) { - if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) { - pos1 = pos1.add(change.getX(), 0, 0); + if (change.x() < 0) { + if (Math.max(pos1.x(), pos2.x()) == pos1.x()) { + pos1 = pos1.add(change.x(), 0, 0); } else { - pos2 = pos2.add(change.getX(), 0, 0); + pos2 = pos2.add(change.x(), 0, 0); } } else { - if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) { - pos1 = pos1.add(change.getX(), 0, 0); + if (Math.min(pos1.x(), pos2.x()) == pos1.x()) { + pos1 = pos1.add(change.x(), 0, 0); } else { - pos2 = pos2.add(change.getX(), 0, 0); + pos2 = pos2.add(change.x(), 0, 0); } } - if (change.getY() < 0) { - if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) { - pos1 = pos1.add(0, change.getY(), 0); + if (change.y() < 0) { + if (Math.max(pos1.y(), pos2.y()) == pos1.y()) { + pos1 = pos1.add(0, change.y(), 0); } else { - pos2 = pos2.add(0, change.getY(), 0); + pos2 = pos2.add(0, change.y(), 0); } } else { - if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) { - pos1 = pos1.add(0, change.getY(), 0); + if (Math.min(pos1.y(), pos2.y()) == pos1.y()) { + pos1 = pos1.add(0, change.y(), 0); } else { - pos2 = pos2.add(0, change.getY(), 0); + pos2 = pos2.add(0, change.y(), 0); } } - if (change.getZ() < 0) { - if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) { - pos1 = pos1.add(0, 0, change.getZ()); + if (change.z() < 0) { + if (Math.max(pos1.z(), pos2.z()) == pos1.z()) { + pos1 = pos1.add(0, 0, change.z()); } else { - pos2 = pos2.add(0, 0, change.getZ()); + pos2 = pos2.add(0, 0, change.z()); } } else { - if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) { - pos1 = pos1.add(0, 0, change.getZ()); + if (Math.min(pos1.z(), pos2.z()) == pos1.z()) { + pos1 = pos1.add(0, 0, change.z()); } else { - pos2 = pos2.add(0, 0, change.getZ()); + pos2 = pos2.add(0, 0, change.z()); } } } @@ -386,10 +385,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { public Set getChunks() { BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - final int maxX = max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; - final int minX = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; - final int maxZ = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; - final int minZ = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; + final int maxX = max.x() >> ChunkStore.CHUNK_SHIFTS; + final int minX = min.x() >> ChunkStore.CHUNK_SHIFTS; + final int maxZ = max.z() >> ChunkStore.CHUNK_SHIFTS; + final int minZ = min.z() >> ChunkStore.CHUNK_SHIFTS; final int size = (maxX - minX + 1) * (maxZ - minZ + 1); //FAWE start @@ -472,7 +471,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { public boolean contains(Object o) { if (o instanceof BlockVector2) { BlockVector2 cv = (BlockVector2) o; - return cv.getX() >= minX && cv.getX() <= maxX && cv.getZ() >= minZ && cv.getZ() <= maxZ; + return cv.x() >= minX && cv.x() <= maxX && cv.z() >= minZ && cv.z() <= maxZ; } return false; } @@ -489,9 +488,9 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - for (int x = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; x <= max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; ++x) { - for (int z = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z <= max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; ++z) { - for (int y = min.getBlockY() >> ChunkStore.CHUNK_SHIFTS; y <= max.getBlockY() >> ChunkStore.CHUNK_SHIFTS; ++y) { + for (int x = min.x() >> ChunkStore.CHUNK_SHIFTS; x <= max.x() >> ChunkStore.CHUNK_SHIFTS; ++x) { + for (int z = min.z() >> ChunkStore.CHUNK_SHIFTS; z <= max.z() >> ChunkStore.CHUNK_SHIFTS; ++z) { + for (int y = min.y() >> ChunkStore.CHUNK_SHIFTS; y <= max.y() >> ChunkStore.CHUNK_SHIFTS; ++y) { chunks.add(BlockVector3.at(x, y, z)); } } @@ -504,7 +503,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { @Override public boolean contains(BlockVector3 position) { //FAWE start - return contains(position.getX(), position.getY(), position.getZ()); + return contains(position.x(), position.y(), position.z()); //FAWE end } @@ -533,17 +532,17 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { private final BlockVector3 min = getMinimumPoint(); private final BlockVector3 max = getMaximumPoint(); - final int bx = min.getBlockX(); - final int by = min.getBlockY(); - final int bz = min.getBlockZ(); + final int bx = min.x(); + final int by = min.y(); + final int bz = min.z(); - final int tx = max.getBlockX(); - final int ty = max.getBlockY(); - final int tz = max.getBlockZ(); + final int tx = max.x(); + final int ty = max.y(); + final int tz = max.z(); - private int x = min.getBlockX(); - private int y = min.getBlockY(); - private int z = min.getBlockZ(); + private int x = min.x(); + private int y = min.y(); + private int z = min.z(); int cx = x >> 4; int cz = z >> 4; @@ -612,9 +611,9 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return new Iterator() { private final BlockVector3 min = getMinimumPoint(); private final BlockVector3 max = getMaximumPoint(); - private int nextX = min.getBlockX(); - private int nextY = min.getBlockY(); - private int nextZ = min.getBlockZ(); + private int nextX = min.x(); + private int nextY = min.y(); + private int nextZ = min.z(); private boolean hasNext = true; @Override @@ -627,17 +626,17 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { mutable.mutX(nextX); mutable.mutY(nextY); mutable.mutZ(nextZ); - if (++nextX > max.getBlockX()) { - nextX = min.getBlockX(); - if (++nextZ > max.getBlockZ()) { - nextZ = min.getBlockZ(); - if (++nextY > max.getBlockY()) { + if (++nextX > max.x()) { + nextX = min.x(); + if (++nextZ > max.z()) { + nextZ = min.z(); + if (++nextY > max.y()) { if (!hasNext()) { throw new NoSuchElementException(); } - nextX = max.getBlockX(); - nextZ = max.getBlockZ(); - nextY = max.getBlockY(); + nextX = max.x(); + nextZ = max.z(); + nextY = max.y(); hasNext = false; } } @@ -653,8 +652,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return () -> new Iterator() { private final BlockVector3 min = getMinimumPoint(); private final BlockVector3 max = getMaximumPoint(); - private int nextX = min.getBlockX(); - private int nextZ = min.getBlockZ(); + private int nextX = min.x(); + private int nextZ = min.z(); @Override public boolean hasNext() { @@ -667,9 +666,9 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { throw new NoSuchElementException(); } BlockVector2 answer = BlockVector2.at(nextX, nextZ); - if (++nextX > max.getBlockX()) { - nextX = min.getBlockX(); - if (++nextZ > max.getBlockZ()) { + if (++nextX > max.x()) { + nextX = min.x(); + if (++nextZ > max.z()) { nextZ = Integer.MAX_VALUE; nextX = Integer.MAX_VALUE; } @@ -706,10 +705,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { public static boolean contains(CuboidRegion region) { BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); - return region.contains(min.getBlockX(), min.getBlockY(), min.getBlockZ()) && region.contains( - max.getBlockX(), - max.getBlockY(), - max.getBlockZ() + return region.contains(min.x(), min.y(), min.z()) && region.contains( + max.x(), + max.y(), + max.z() ); } //FAWE end @@ -756,7 +755,6 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { ) { int chunkX = chunk.getX(); int chunkZ = chunk.getZ(); - block = block.initChunk(chunkX, chunkZ); //Chunk entry is an "interior chunk" in regards to the entire region, so filter the chunk whole instead of partially if ((minX + 15) >> 4 <= chunkX && (maxX - 15) >> 4 >= chunkX && (minZ + 15) >> 4 <= chunkZ && (maxZ - 15) >> 4 >= chunkZ) { @@ -805,7 +803,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return set; } trimY(set, minY, maxY, true); - trimNBT(set, this::contains); + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos))); return set; } if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) { @@ -828,7 +827,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return set; } - for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) { + for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { if (!set.hasSection(layer)) { continue; } @@ -868,8 +867,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { } set.setBlocks(layer, arr); } - - trimNBT(set, this::contains); + final BlockVector3 chunkPos = BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4); + trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos))); return set; } return null; @@ -893,7 +892,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return null; } trimY(set, minY, maxY, false); - trimNBT(set, this::contains); + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos))); return set; } if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) { @@ -911,7 +911,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { boolean trimX = lowerX != 0 || upperX != 15; boolean trimZ = lowerZ != 0 || upperZ != 15; - for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) { + for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { if (!set.hasSection(layer)) { continue; } @@ -943,7 +943,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { } set.setBlocks(layer, arr); } - trimNBT(set, bv3 -> !this.contains(bv3)); + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + trimNBT(set, bv3 -> !this.contains(bv3), bv3 -> !this.contains(bv3.add(chunkPos))); return set; } return set; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java index 03b38a55c..85c62e771 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java @@ -141,7 +141,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { */ public void setRadius(Vector2 radius) { this.radius = radius.add(0.5, 0.5); - this.radiusInverse = Vector2.ONE.divide(radius); + this.radiusInverse = Vector2.ONE.divide(this.radius); } /** @@ -197,8 +197,8 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { @Override public long getVolume() { - return BigDecimal.valueOf(radius.getX()) - .multiply(BigDecimal.valueOf(radius.getZ())) + return BigDecimal.valueOf(radius.x()) + .multiply(BigDecimal.valueOf(radius.z())) .multiply(PI) .multiply(BigDecimal.valueOf(getHeight())) .setScale(0, RoundingMode.FLOOR) @@ -207,7 +207,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { @Override public int getWidth() { - return (int) (2 * radius.getX()); + return (int) (2 * radius.x()); } @Override @@ -217,7 +217,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { @Override public int getLength() { - return (int) (2 * radius.getZ()); + return (int) (2 * radius.z()); } private BlockVector2 calculateDiff2D(BlockVector3... changes) throws RegionOperationException { @@ -226,7 +226,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { diff = diff.add(change.toBlockVector2()); } - if ((diff.getBlockX() & 1) + (diff.getBlockZ() & 1) != 0) { + if ((diff.x() & 1) + (diff.z() & 1) != 0) { throw new RegionOperationException(Caption.of("worldedit.selection.cylinder.error.even-horizontal")); } @@ -254,7 +254,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { radius = radius.add(calculateChanges2D(changes).toVector2()); this.radiusInverse = Vector2.ONE.divide(radius); for (BlockVector3 change : changes) { - int changeY = change.getBlockY(); + int changeY = change.y(); if (changeY > 0) { maxY += changeY; } else { @@ -276,7 +276,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { this.radiusInverse = Vector2.ONE.divide(radius); for (BlockVector3 change : changes) { int height = maxY - minY; - int changeY = change.getBlockY(); + int changeY = change.y(); if (changeY > 0) { minY += Math.min(height, changeY); } else { @@ -289,7 +289,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { public void shift(BlockVector3 change) throws RegionOperationException { center = center.add(change.toBlockVector2()); - int changeY = change.getBlockY(); + int changeY = change.y(); maxY += changeY; minY += changeY; } @@ -322,15 +322,15 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { @Override public boolean contains(int x, int z) { - double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX(); - double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ(); + double dx = Math.abs(x - center.x()) * radiusInverse.x(); + double dz = Math.abs(z - center.z()) * radiusInverse.z(); return dx * dx + dz * dz <= 1; } @Override public boolean contains(BlockVector3 position) { - return contains(position.getX(), position.getY(), position.getZ()); + return contains(position.x(), position.y(), position.z()); } //FAWE end @@ -402,8 +402,8 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { checkNotNull(extent); checkNotNull(center); Vector2 radiusVec = Vector2.at(radius, radius); - int minY = extent.getMinimumPoint().getBlockY(); - int maxY = extent.getMaximumPoint().getBlockY(); + int minY = extent.getMinimumPoint().y(); + int maxY = extent.getMaximumPoint().y(); return new CylinderRegion(center, radiusVec, minY, maxY); } @@ -413,11 +413,12 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { final IChunk chunk, final Filter filter, final ChunkFilterBlock block, final IChunkGet get, final IChunkSet set, boolean full ) { - int bcx = chunk.getX() >> 4; - int bcz = chunk.getZ() >> 4; + int bcx = chunk.getX() << 4; + int bcz = chunk.getZ() << 4; int tcx = bcx + 15; int tcz = bcz + 15; - if (contains(bcx, bcz) && contains(tcx, tcz)) { + // must contain all 4 corners for fast path + if (contains(bcx, bcz) && contains(tcx, tcz) && contains(bcx, tcz) && contains(tcx, bcz)) { filter(chunk, filter, block, get, set, minY, maxY, full); return; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java index c3aed2a53..1bc13ed43 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java @@ -102,32 +102,32 @@ public class EllipsoidRegion extends AbstractRegion { @Override public long getVolume() { return ELLIPSOID_BASE_MULTIPLIER - .multiply(BigDecimal.valueOf(radius.getX())) - .multiply(BigDecimal.valueOf(radius.getY())) - .multiply(BigDecimal.valueOf(radius.getZ())) + .multiply(BigDecimal.valueOf(radius.x())) + .multiply(BigDecimal.valueOf(radius.y())) + .multiply(BigDecimal.valueOf(radius.z())) .setScale(0, RoundingMode.FLOOR) .longValue(); } @Override public int getWidth() { - return (int) (2 * radius.getX()); + return (int) (2 * radius.x()); } @Override public int getHeight() { - return (int) (2 * radius.getY()); + return (int) (2 * radius.y()); } @Override public int getLength() { - return (int) (2 * radius.getZ()); + return (int) (2 * radius.z()); } private BlockVector3 calculateDiff(BlockVector3... changes) throws RegionOperationException { BlockVector3 diff = BlockVector3.ZERO.add(changes); - if ((diff.getBlockX() & 1) + (diff.getBlockY() & 1) + (diff.getBlockZ() & 1) != 0) { + if ((diff.x() & 1) + (diff.y() & 1) + (diff.z() & 1) != 0) { throw new RegionOperationException(Caption.of("worldedit.selection.ellipsoid.error.even-horizontal")); } @@ -198,8 +198,8 @@ public class EllipsoidRegion extends AbstractRegion { this.radius = radius.add(0.5, 0.5, 0.5); //FAWE start radiusSqr = radius.multiply(radius); - radiusLengthSqr = (int) radiusSqr.getX(); - this.sphere = radius.getY() == radius.getX() && radius.getX() == radius.getZ(); + radiusLengthSqr = (int) radiusSqr.x(); + this.sphere = radius.y() == radius.x() && radius.x() == radius.z(); inverseRadiusSqr = Vector3.ONE.divide(radiusSqr); //FAWE end } @@ -210,10 +210,10 @@ public class EllipsoidRegion extends AbstractRegion { final BlockVector3 min = getMinimumPoint(); final BlockVector3 max = getMaximumPoint(); - final int centerY = center.getBlockY(); + final int centerY = center.y(); - for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) { + for (int x = min.x(); x <= max.x(); ++x) { + for (int z = min.z(); z <= max.z(); ++z) { if (!contains(x, centerY, z)) { continue; } @@ -231,17 +231,17 @@ public class EllipsoidRegion extends AbstractRegion { //FAWE start @Override public boolean contains(int x, int y, int z) { - int cx = x - center.getBlockX(); + int cx = x - center.x(); int cx2 = cx * cx; if (cx2 > radiusSqr.getBlockX()) { return false; } - int cz = z - center.getBlockZ(); + int cz = z - center.z(); int cz2 = cz * cz; if (cz2 > radiusSqr.getBlockZ()) { return false; } - int cy = y - center.getBlockY(); + int cy = y - center.y(); int cy2 = cy * cy; if (radiusSqr.getBlockY() < getWorldMaxY() && cy2 > radiusSqr.getBlockY()) { return false; @@ -249,9 +249,9 @@ public class EllipsoidRegion extends AbstractRegion { if (sphere) { return cx2 + cy2 + cz2 <= radiusLengthSqr; } - double cxd = cx2 * inverseRadiusSqr.getX(); - double cyd = cy2 * inverseRadiusSqr.getY(); - double czd = cz2 * inverseRadiusSqr.getZ(); + double cxd = cx2 * inverseRadiusSqr.x(); + double cyd = cy2 * inverseRadiusSqr.y(); + double czd = cz2 * inverseRadiusSqr.z(); return cxd + cyd + czd <= 1; } @@ -265,23 +265,23 @@ public class EllipsoidRegion extends AbstractRegion { @Override public boolean contains(BlockVector3 position) { - return contains(position.getX(), position.getY(), position.getZ()); + return contains(position.x(), position.y(), position.z()); } @Override public boolean contains(int x, int z) { - int cx = x - center.getBlockX(); + int cx = x - center.x(); int cx2 = cx * cx; if (cx2 > radiusSqr.getBlockX()) { return false; } - int cz = z - center.getBlockZ(); + int cz = z - center.z(); int cz2 = cz * cz; if (cz2 > radiusSqr.getBlockZ()) { return false; } - double cxd = cx2 * inverseRadiusSqr.getX(); - double czd = cz2 * inverseRadiusSqr.getZ(); + double cxd = cx2 * inverseRadiusSqr.x(); + double czd = cz2 * inverseRadiusSqr.z(); return cxd + czd <= 1; } //FAWE end @@ -339,9 +339,9 @@ public class EllipsoidRegion extends AbstractRegion { int layer, int y1, int y2, int bx, int bz, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set ) { - int cx = center.getBlockX(); - int cy = center.getBlockY(); - int cz = center.getBlockZ(); + int cx = center.x(); + int cy = center.y(); + int cz = center.z(); block.initLayer(get, set, layer); @@ -376,8 +376,8 @@ public class EllipsoidRegion extends AbstractRegion { ) { // Check bounds // This needs to be able to perform 50M blocks/sec otherwise it becomes a bottleneck - int cx = center.getBlockX(); - int cz = center.getBlockZ(); + int cx = center.x(); + int cz = center.z(); int bx = chunk.getX() << 4; int bz = chunk.getZ() << 4; int tx = bx + 15; @@ -412,10 +412,8 @@ public class EllipsoidRegion extends AbstractRegion { return; } - block = block.initChunk(chunk.getX(), chunk.getZ()); - // Get the solid layers - int cy = center.getBlockY(); + int cy = center.y(); int diffYFull = MathMan.usqrt(diffY2); int yBotFull = Math.max(getWorldMinY(), cy - diffYFull); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java index 021e042be..b07503762 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java @@ -111,14 +111,14 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { return; } - int minX = points.get(0).getBlockX(); - int minZ = points.get(0).getBlockZ(); - int maxX = points.get(0).getBlockX(); - int maxZ = points.get(0).getBlockZ(); + int minX = points.get(0).x(); + int minZ = points.get(0).z(); + int maxX = points.get(0).x(); + int maxZ = points.get(0).z(); for (BlockVector2 v : points) { - int x = v.getBlockX(); - int z = v.getBlockZ(); + int x = v.x(); + int z = v.z(); if (x < minX) { minX = x; } @@ -161,7 +161,7 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { * @param position the position */ public void addPoint(BlockVector3 position) { - points.add(BlockVector2.at(position.getBlockX(), position.getBlockZ())); + points.add(BlockVector2.at(position.x(), position.z())); recalculate(); } @@ -214,8 +214,8 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { int j = points.size() - 1; for (i = 0; i < points.size(); ++i) { - long x = points.get(j).getBlockX() + points.get(i).getBlockX(); - long z = points.get(j).getBlockZ() - points.get(i).getBlockZ(); + long x = points.get(j).x() + points.get(i).x(); + long z = points.get(j).z() - points.get(i).z(); area += x * z; j = i; } @@ -229,7 +229,7 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { @Override public int getWidth() { - return max.getBlockX() - min.getBlockX() + 1; + return max.x() - min.x() + 1; } @Override @@ -239,16 +239,16 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { @Override public int getLength() { - return max.getBlockZ() - min.getBlockZ() + 1; + return max.z() - min.z() + 1; } @Override public void expand(BlockVector3... changes) throws RegionOperationException { for (BlockVector3 change : changes) { - if (change.getBlockX() != 0 || change.getBlockZ() != 0) { + if (change.x() != 0 || change.z() != 0) { throw new RegionOperationException(Caption.of("worldedit.selection.polygon2d.error.expand-only-vertical")); } - int changeY = change.getBlockY(); + int changeY = change.y(); if (changeY > 0) { maxY += changeY; } else { @@ -261,10 +261,10 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { @Override public void contract(BlockVector3... changes) throws RegionOperationException { for (BlockVector3 change : changes) { - if (change.getBlockX() != 0 || change.getBlockZ() != 0) { + if (change.x() != 0 || change.z() != 0) { throw new RegionOperationException(Caption.of("worldedit.selection.polygon2d.error.contract-only-vertical")); } - int changeY = change.getBlockY(); + int changeY = change.y(); if (changeY > 0) { minY += changeY; } else { @@ -276,13 +276,13 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { @Override public void shift(BlockVector3 change) throws RegionOperationException { - final double changeX = change.getX(); - final double changeY = change.getY(); - final double changeZ = change.getZ(); + final double changeX = change.x(); + final double changeY = change.y(); + final double changeZ = change.z(); for (int i = 0; i < points.size(); ++i) { BlockVector2 point = points.get(i); - points.set(i, BlockVector2.at(point.getX() + changeX, point.getZ() + changeZ)); + points.set(i, BlockVector2.at(point.x() + changeX, point.z() + changeZ)); } minY += changeY; @@ -307,12 +307,12 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { long crossproduct; int i; - xOld = points.get(npoints - 1).getBlockX(); - zOld = points.get(npoints - 1).getBlockZ(); + xOld = points.get(npoints - 1).x(); + zOld = points.get(npoints - 1).z(); for (i = 0; i < npoints; ++i) { - xNew = points.get(i).getBlockX(); - zNew = points.get(i).getBlockZ(); + xNew = points.get(i).x(); + zNew = points.get(i).z(); //Check for corner if (xNew == targetX && zNew == targetZ) { return true; @@ -365,9 +365,9 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { if (points.size() < 3) { return false; } - int targetX = pt.getBlockX(); //wide - int targetY = pt.getBlockY(); //height - int targetZ = pt.getBlockZ(); //depth + int targetX = pt.x(); //wide + int targetY = pt.y(); //height + int targetZ = pt.z(); //depth if (targetY < minY || targetY > maxY) { return false; @@ -384,12 +384,12 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { long crossproduct; int i; - int xOld = points.get(npoints - 1).getBlockX(); - int zOld = points.get(npoints - 1).getBlockZ(); + int xOld = points.get(npoints - 1).x(); + int zOld = points.get(npoints - 1).z(); for (i = 0; i < npoints; ++i) { - xNew = points.get(i).getBlockX(); - zNew = points.get(i).getBlockZ(); + xNew = points.get(i).x(); + zNew = points.get(i).z(); //Check for corner if (xNew == targetX && zNew == targetZ) { return true; @@ -478,7 +478,7 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { Iterator it = pts.iterator(); while (it.hasNext()) { BlockVector2 current = it.next(); - sb.append("(").append(current.getBlockX()).append(", ").append(current.getBlockZ()).append(")"); + sb.append("(").append(current.x()).append(", ").append(current.z()).append(")"); if (it.hasNext()) { sb.append(" - "); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java index b89536520..c236992cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -235,15 +235,15 @@ public interface Region extends Iterable, Cloneable, IBatchProcess default boolean isGlobal() { BlockVector3 pos1 = getMinimumPoint(); BlockVector3 pos2 = getMaximumPoint(); - return pos1.getBlockX() == Integer.MIN_VALUE && pos1.getBlockZ() == Integer.MIN_VALUE && pos2.getBlockX() == Integer.MAX_VALUE && pos2 - .getBlockZ() == Integer.MAX_VALUE - && pos1.getBlockY() <= WorldEdit + return pos1.x() == Integer.MIN_VALUE && pos1.z() == Integer.MIN_VALUE && pos2.x() == Integer.MAX_VALUE && pos2 + .z() == Integer.MAX_VALUE + && pos1.y() <= WorldEdit .getInstance() .getPlatformManager() .queryCapability( Capability.WORLD_EDITING) .versionMinY() - && pos2.getBlockY() >= WorldEdit + && pos2.y() >= WorldEdit .getInstance() .getPlatformManager() .queryCapability(Capability.WORLD_EDITING) @@ -251,11 +251,11 @@ public interface Region extends Iterable, Cloneable, IBatchProcess } default int getMinimumY() { - return getMinimumPoint().getY(); + return getMinimumPoint().y(); } default int getMaximumY() { - return getMaximumPoint().getY(); + return getMaximumPoint().y(); } default void filter( @@ -268,9 +268,9 @@ public interface Region extends Iterable, Cloneable, IBatchProcess ) { int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4); int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4); - block = block.initChunk(chunk.getX(), chunk.getZ()); for (int layer = minSection; layer <= maxSection; layer++) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -320,7 +320,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int layer, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -342,7 +343,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int maxZ, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -360,7 +362,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int yEnd, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -385,7 +388,7 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int tz = bz + 15; BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - return tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ(); + return tx >= min.x() && bx <= max.x() && tz >= min.z() && bz <= max.z(); } @Override @@ -397,7 +400,7 @@ public interface Region extends Iterable, Cloneable, IBatchProcess BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - if (tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ()) { + if (tx >= min.x() && bx <= max.x() && tz >= min.z() && bz <= max.z()) { // contains some boolean processExtra = false; for (int layer = getMinimumY() >> 4; layer <= getMaximumY() >> 4; layer++) { @@ -425,7 +428,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess } } if (processExtra) { - trimNBT(set, this::contains); + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos))); } return set; } else { @@ -450,7 +454,7 @@ public interface Region extends Iterable, Cloneable, IBatchProcess BlockVector3 min = getMinimumPoint(); BlockVector3 max = getMaximumPoint(); - if (tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ()) { + if (tx >= min.x() && bx <= max.x() && tz >= min.z() && bz <= max.z()) { // contains some boolean processExtra = false; for (int layer = getMinimumY() >> 4; layer <= getMaximumY() >> 4; layer++) { @@ -477,11 +481,12 @@ public interface Region extends Iterable, Cloneable, IBatchProcess } } if (processExtra) { - trimNBT(set, bv3 -> !this.contains(bv3)); + BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); + trimNBT(set, bv3 -> !this.contains(bv3), bv3 -> !this.contains(bv3.add(chunkPos))); } return set; } else { - return null; + return set; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java index 8298a8b00..4312e50fa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java @@ -164,14 +164,23 @@ public class RegionIntersection extends AbstractRegion { int bz = chunk.getZ() << 4; int tx = bx + 15; int tz = bz + 15; + List intersecting = new ArrayList<>(2); for (Region region : regions) { BlockVector3 regMin = region.getMinimumPoint(); BlockVector3 regMax = region.getMaximumPoint(); - if (tx >= regMin.getX() && bx <= regMax.getX() && tz >= regMin.getZ() && bz <= regMax.getZ()) { - return region.processSet(chunk, get, set); + if (tx >= regMin.x() && bx <= regMax.x() && tz >= regMin.z() && bz <= regMax.z()) { + intersecting.add(region); } } - return null; + if (intersecting.isEmpty()) { + return null; + } + if (intersecting.size() == 1) { + return intersecting.get(0).processSet(chunk, get, set); + } + // if multiple regions intersect with this chunk, we must be more careful, otherwise one region might trim content of + // another region + return super.processSet(chunk, get, set); } @Override @@ -195,8 +204,8 @@ public class RegionIntersection extends AbstractRegion { for (Region region : regions) { BlockVector3 regMin = region.getMinimumPoint(); BlockVector3 regMax = region.getMaximumPoint(); - if (tx >= regMin.getX() && bx <= regMax.getX() && tz >= regMin.getZ() && bz <= regMax.getZ()) { - return region.processSet(chunk, get, set, true); + if (tx >= regMin.x() && bx <= regMax.x() && tz >= regMin.z() && bz <= regMax.z()) { + set = region.processSet(chunk, get, set, true); } } return set; // default return set as no "blacklist" regions contained the chunk diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Regions.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Regions.java index 040ec2803..d562190cb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Regions.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Regions.java @@ -35,7 +35,7 @@ public final class Regions { * @return the Y coordinate */ public static double minimumY(Region region) { - return region.getMinimumPoint().getY(); + return region.getMinimumPoint().y(); } /** @@ -46,7 +46,7 @@ public final class Regions { * @return the Y coordinate */ public static double maximumY(Region region) { - return region.getMaximumPoint().getY(); + return region.getMaximumPoint().y(); } /** @@ -57,7 +57,7 @@ public final class Regions { * @return the Y coordinate */ public static int minimumBlockY(Region region) { - return region.getMinimumPoint().getBlockY(); + return region.getMinimumPoint().y(); } /** @@ -68,7 +68,7 @@ public final class Regions { * @return the Y coordinate */ public static int maximumBlockY(Region region) { - return region.getMaximumPoint().getBlockY(); + return region.getMaximumPoint().y(); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java index b2471af32..782fcebae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java @@ -119,17 +119,17 @@ public class TransformRegion extends AbstractRegion { @Override public int getWidth() { - return getMaximumPoint().subtract(getMinimumPoint()).getBlockX() + 1; + return getMaximumPoint().subtract(getMinimumPoint()).x() + 1; } @Override public int getHeight() { - return getMaximumPoint().subtract(getMinimumPoint()).getBlockY() + 1; + return getMaximumPoint().subtract(getMinimumPoint()).y() + 1; } @Override public int getLength() { - return getMaximumPoint().subtract(getMinimumPoint()).getBlockZ() + 1; + return getMaximumPoint().subtract(getMinimumPoint()).z() + 1; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/factory/CylinderRegionFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/factory/CylinderRegionFactory.java index 386700b1e..67112c68c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/factory/CylinderRegionFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/factory/CylinderRegionFactory.java @@ -37,8 +37,8 @@ public class CylinderRegionFactory implements RegionFactory { return new CylinderRegion( position, Vector2.at(size, size), - position.getBlockY() - (int) (height / 2), - position.getBlockY() + (int) (height / 2) + position.y() - (int) (height / 2), + position.y() + (int) (height / 2) ); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegion3DIterator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegion3DIterator.java index e7ae99340..12c5f90d9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegion3DIterator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegion3DIterator.java @@ -68,7 +68,7 @@ public class FlatRegion3DIterator implements Iterator { throw new NoSuchElementException(); } - BlockVector3 current = BlockVector3.at(next2D.getBlockX(), nextY, next2D.getBlockZ()); + BlockVector3 current = BlockVector3.at(next2D.x(), nextY, next2D.z()); if (nextY < maxY) { nextY++; } else if (flatIterator.hasNext()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegionIterator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegionIterator.java index e62c72ecd..3db019499 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegionIterator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/FlatRegionIterator.java @@ -46,15 +46,15 @@ public class FlatRegionIterator implements Iterator { BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); - this.y = min.getBlockY(); + this.y = min.y(); - this.minX = min.getBlockX(); + this.minX = min.x(); this.nextX = minX; - this.nextZ = min.getBlockZ(); + this.nextZ = min.z(); - this.maxX = max.getBlockX(); - this.maxZ = max.getBlockZ(); + this.maxX = max.x(); + this.maxZ = max.z(); forward(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/RegionIterator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/RegionIterator.java index 9e2c9b8e8..54f67b4de 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/RegionIterator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/iterator/RegionIterator.java @@ -43,14 +43,14 @@ public class RegionIterator implements Iterator { this.region = region; BlockVector3 max = region.getMaximumPoint(); - this.maxX = max.getBlockX(); - this.maxY = max.getBlockY(); - this.maxZ = max.getBlockZ(); + this.maxX = max.x(); + this.maxY = max.y(); + this.maxZ = max.z(); this.min = region.getMinimumPoint(); - this.nextX = min.getBlockX(); - this.nextY = min.getBlockY(); - this.nextZ = min.getBlockZ(); + this.nextX = min.x(); + this.nextY = min.y(); + this.nextZ = min.z(); forward(); } @@ -84,12 +84,12 @@ public class RegionIterator implements Iterator { if (++nextX <= maxX) { return; } - nextX = min.getBlockX(); + nextX = min.x(); if (++nextY <= maxY) { return; } - nextY = min.getBlockY(); + nextY = min.y(); if (++nextZ <= maxZ) { return; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java index 70471ceae..ac3141c02 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java @@ -101,8 +101,8 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion return; } - final int minY = oldRegion.getMinimumPoint().getBlockY(); - final int maxY = oldRegion.getMaximumPoint().getBlockY(); + final int minY = oldRegion.getMinimumPoint().y(); + final int maxY = oldRegion.getMaximumPoint().y(); region = new ConvexPolyhedralRegion(oldRegion.getWorld()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java index 689cd3701..5a9d3748b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java @@ -115,8 +115,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { region.setCenter(center.toBlockVector2()); region.setRadius(pos2.toBlockVector2().subtract(center.toBlockVector2()).toVector2()); - region.setMaximumY(Math.max(pos1.getBlockY(), pos2.getBlockY())); - region.setMinimumY(Math.min(pos1.getBlockY(), pos2.getBlockY())); + region.setMaximumY(Math.max(pos1.y(), pos2.y())); + region.setMinimumY(Math.min(pos1.y(), pos2.y())); selectedCenter = true; selectedRadius = true; @@ -164,7 +164,7 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { region = new CylinderRegion(region.getWorld()); region.setCenter(position.toBlockVector2()); - region.setY(position.getBlockY()); + region.setY(position.y()); selectedCenter = true; selectedRadius = false; @@ -182,7 +182,7 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { final Vector2 minRadius = diff.getMaximum(diff.multiply(-1.0)); region.extendRadius(minRadius); - region.setY(position.getBlockY()); + region.setY(position.y()); selectedRadius = true; @@ -201,8 +201,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { if (selectedCenter) { player.print(Caption.of( "worldedit.selection.cylinder.explain.secondary", - TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getX())), - TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getZ())), + TextComponent.of(NUMBER_FORMAT.format(region.getRadius().x())), + TextComponent.of(NUMBER_FORMAT.format(region.getRadius().z())), TextComponent.of(region.getVolume()) )); } else { @@ -254,6 +254,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { @Override public void clear() { region = new CylinderRegion(region.getWorld()); + selectedCenter = false; + selectedRadius = false; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java index 02d570969..1f7c8a420 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java @@ -227,6 +227,8 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion { public void clear() { region.setCenter(BlockVector3.ZERO); region.setRadius(Vector3.ZERO); + started = false; + selectedRadius = false; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java index 5d74d7ae6..e75f8bbb5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java @@ -107,13 +107,13 @@ public class ExtendingCuboidRegionSelector extends CuboidRegionSelector { return false; } - double x1 = Math.min(position.getX(), position1.getX()); - double y1 = Math.min(position.getY(), position1.getY()); - double z1 = Math.min(position.getZ(), position1.getZ()); + double x1 = Math.min(position.x(), position1.x()); + double y1 = Math.min(position.y(), position1.y()); + double z1 = Math.min(position.z(), position1.z()); - double x2 = Math.max(position.getX(), position2.getX()); - double y2 = Math.max(position.getY(), position2.getY()); - double z2 = Math.max(position.getZ(), position2.getZ()); + double x2 = Math.max(position.x(), position2.x()); + double y2 = Math.max(position.y(), position2.y()); + double z2 = Math.max(position.z(), position2.z()); final BlockVector3 o1 = position1; final BlockVector3 o2 = position2; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/Polygonal2DRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/Polygonal2DRegionSelector.java index bf472615a..be9134f15 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/Polygonal2DRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/Polygonal2DRegionSelector.java @@ -96,8 +96,8 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { return; } - final int minY = oldRegion.getMinimumPoint().getBlockY(); - final int maxY = oldRegion.getMaximumPoint().getBlockY(); + final int minY = oldRegion.getMinimumPoint().y(); + final int maxY = oldRegion.getMaximumPoint().y(); List points = oldRegion.polygonize(Integer.MAX_VALUE); @@ -118,7 +118,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { checkNotNull(points); final BlockVector2 pos2D = points.get(0); - pos1 = BlockVector3.at(pos2D.getX(), minY, pos2D.getZ()); + pos1 = BlockVector3.at(pos2D.x(), minY, pos2D.z()); region = new Polygonal2DRegion(world, points, minY, maxY); } @@ -142,7 +142,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { pos1 = position; region = new Polygonal2DRegion(region.getWorld()); region.addPoint(position); - region.expandY(position.getBlockY()); + region.expandY(position.y()); return true; } @@ -153,7 +153,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { final List points = region.getPoints(); final BlockVector2 lastPoint = points.get(region.size() - 1); - if (lastPoint.getBlockX() == position.getBlockX() && lastPoint.getBlockZ() == position.getBlockZ()) { + if (lastPoint.x() == position.x() && lastPoint.z() == position.z()) { return false; } @@ -165,7 +165,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { } region.addPoint(position); - region.expandY(position.getBlockY()); + region.expandY(position.y()); return true; } @@ -228,7 +228,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { @Override public void learnChanges() { BlockVector2 pt = region.getPoints().get(0); - pos1 = BlockVector3.at(pt.getBlockX(), region.getMinimumPoint().getBlockY(), pt.getBlockZ()); + pos1 = BlockVector3.at(pt.x(), region.getMinimumPoint().y(), pt.z()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/RegionSelectorType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/RegionSelectorType.java index 61e46aeab..c76b058b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/RegionSelectorType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/RegionSelectorType.java @@ -19,8 +19,14 @@ package com.sk89q.worldedit.regions.selector; +import com.fastasyncworldedit.core.regions.selector.FuzzyRegionSelector; +import com.fastasyncworldedit.core.regions.selector.PolyhedralRegionSelector; import com.sk89q.worldedit.regions.RegionSelector; +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + /** * An enum of default region selector types. */ @@ -32,7 +38,21 @@ public enum RegionSelectorType { SPHERE(SphereRegionSelector.class), ELLIPSOID(EllipsoidRegionSelector.class), POLYGON(Polygonal2DRegionSelector.class), - CONVEX_POLYHEDRON(ConvexPolyhedralRegionSelector.class); + CONVEX_POLYHEDRON(ConvexPolyhedralRegionSelector.class), + //FAWE start + POLYHEDRAL(PolyhedralRegionSelector.class), + FUZZY(FuzzyRegionSelector.class); + //FAWE end + + //FAWE start + private static final Map, RegionSelectorType> VALUE_MAP = new HashMap<>(); + + static { + for (RegionSelectorType type : values()) { + VALUE_MAP.put(type.getSelectorClass(), type); + } + } + //FAWE end private final Class selectorClass; @@ -40,6 +60,19 @@ public enum RegionSelectorType { this.selectorClass = selectorClass; } + //FAWE start + /** + * Get a {@link RegionSelectorType} for the given {@link RegionSelector} + * + * @param selector Region selector to get type enum for + * @since 2.9.2 + */ + @Nullable + public static RegionSelectorType getForSelector(RegionSelector selector) { + return VALUE_MAP.get(selector.getClass()); + } + //FAWE end + /** * Get the selector class. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java index a0eff3046..7394015ab 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java @@ -61,7 +61,7 @@ public class SphereRegionSelector extends EllipsoidRegionSelector { super(oldSelector); if (selectedRadius) { final Vector3 radius = region.getRadius(); - final double radiusScalar = Math.max(Math.max(radius.getX(), radius.getY()), radius.getZ()); + final double radiusScalar = Math.max(Math.max(radius.x(), radius.y()), radius.z()); region.setRadius(Vector3.at(radiusScalar, radiusScalar, radiusScalar)); } } @@ -96,11 +96,11 @@ public class SphereRegionSelector extends EllipsoidRegionSelector { if (isDefined()) { player.print(Caption.of( "worldedit.selection.sphere.explain.secondary-defined", - TextComponent.of(region.getRadius().getX()), + TextComponent.of(region.getRadius().x()), TextComponent.of(region.getVolume()) )); } else { - player.print(Caption.of("worldedit.selection.sphere.explain.secondary", TextComponent.of(region.getRadius().getX()))); + player.print(Caption.of("worldedit.selection.sphere.explain.secondary", TextComponent.of(region.getRadius().x()))); } session.describeCUI(player); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryBiomeShape.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryBiomeShape.java index 9f2ef87b0..2fb9e6588 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryBiomeShape.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryBiomeShape.java @@ -59,13 +59,13 @@ public abstract class ArbitraryBiomeShape { BlockVector3 min = extent.getMinimumPoint(); BlockVector3 max = extent.getMaximumPoint(); - cacheOffsetX = min.getBlockX() - 1; - cacheOffsetY = min.getBlockY() - 1; - cacheOffsetZ = min.getBlockZ() - 1; + cacheOffsetX = min.x() - 1; + cacheOffsetY = min.y() - 1; + cacheOffsetZ = min.z() - 1; - cacheSizeX = max.getX() - cacheOffsetX + 2; - cacheSizeY = max.getY() - cacheOffsetY + 2; - cacheSizeZ = max.getZ() - cacheOffsetZ + 2; + cacheSizeX = max.x() - cacheOffsetX + 2; + cacheSizeY = max.y() - cacheOffsetY + 2; + cacheSizeZ = max.z() - cacheOffsetZ + 2; cache = new BiomeType[cacheSizeX * cacheSizeY * cacheSizeZ]; isCached = new BitSet(cache.length); @@ -128,9 +128,9 @@ public abstract class ArbitraryBiomeShape { int affected = 0; for (BlockVector3 position : getExtent()) { - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); + int x = position.x(); + int y = position.y(); + int z = position.z(); if (!hollow) { final BiomeType material = getBiome(x, y, z, baseBiome); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java index 4feff6b8f..dbb516b1b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java @@ -59,13 +59,13 @@ public abstract class ArbitraryShape { BlockVector3 min = extent.getMinimumPoint(); BlockVector3 max = extent.getMaximumPoint(); - cacheOffsetX = min.getBlockX() - 1; - cacheOffsetY = min.getBlockY() - 1; - cacheOffsetZ = min.getBlockZ() - 1; + cacheOffsetX = min.x() - 1; + cacheOffsetY = min.y() - 1; + cacheOffsetZ = min.z() - 1; - cacheSizeX = max.getX() - cacheOffsetX + 2; - cacheSizeY = max.getY() - cacheOffsetY + 2; - cacheSizeZ = max.getZ() - cacheOffsetZ + 2; + cacheSizeX = max.x() - cacheOffsetX + 2; + cacheSizeY = max.y() - cacheOffsetY + 2; + cacheSizeZ = max.z() - cacheOffsetZ + 2; cache = new byte[cacheSizeX * cacheSizeY * cacheSizeZ]; } @@ -98,9 +98,9 @@ public abstract class ArbitraryShape { int affected = 0; for (BlockVector3 position : getExtent()) { - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); + int x = position.x(); + int y = position.y(); + int z = position.z(); if (!hollow) { BaseBlock material = getMaterial(x, y, z, pattern.applyBlock(position)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java index 15e93c7db..2284b9733 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java @@ -28,6 +28,8 @@ import com.sk89q.worldedit.math.Vector3; public class WorldEditExpressionEnvironment implements ExpressionEnvironment { + private static final Vector3 BLOCK_CENTER_OFFSET = Vector3.at(0.5, 0.5, 0.5); + private final Vector3 unit; private final Vector3 zero2; //FAWE start - MutableVector3 @@ -42,7 +44,7 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment { public WorldEditExpressionEnvironment(Extent extent, Vector3 unit, Vector3 zero) { this.extent = extent; this.unit = unit; - this.zero2 = zero.add(0.5, 0.5, 0.5); + this.zero2 = zero.add(BLOCK_CENTER_OFFSET); } public BlockVector3 toWorld(double x, double y, double z) { @@ -83,7 +85,7 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment { @SuppressWarnings("deprecation") @Override public int getBlockDataRel(double x, double y, double z) { - return extent.getBlock(toWorld(x, y, z)).getBlockType().getLegacyCombinedId() & 0xF; + return extent.getBlock(toWorldRel(x, y, z).toBlockPoint()).getBlockType().getLegacyCombinedId() & 0xF; } //FAWE start @@ -94,10 +96,13 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment { public Vector3 toWorldRel(double x, double y, double z) { return current.add(x, y, z); } + + public WorldEditExpressionEnvironment clone() { + return new WorldEditExpressionEnvironment(extent, unit, zero2.subtract(BLOCK_CENTER_OFFSET)); + } //FAWe end public void setCurrentBlock(Vector3 current) { this.current = current; } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Category.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Category.java index fc8a5e895..e18499c04 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Category.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Category.java @@ -23,26 +23,39 @@ import com.fastasyncworldedit.core.registry.RegistryItem; import java.util.HashSet; import java.util.Set; +import java.util.function.Supplier; //FAWE start - implements RegistryItem -public abstract class Category implements RegistryItem { +public abstract class Category implements RegistryItem, Keyed { //FAWE end private final Set set = new HashSet<>(); + private final Supplier> supplier; protected final String id; private boolean empty = true; - protected Category(final String id) { + public Category(final String id) { this.id = id; + this.supplier = null; } - public final String getId() { + public Category(String id, Supplier> contentSupplier) { + this.id = id; + this.supplier = contentSupplier; + } + + @Override + public final String id() { return this.id; } public final Set getAll() { if (this.empty) { - this.set.addAll(this.load()); + if (supplier != null) { + this.set.addAll(this.supplier.get()); + } else { + this.set.addAll(this.load()); + } this.empty = false; } return this.set; @@ -61,6 +74,14 @@ public abstract class Category implements RegistryItem { return internalId; } + /** + * Loads the contents of this category from the platform. + * + * @return The loaded contents of the category + * @deprecated The load system will be removed in a future WorldEdit release. The registries should be populated by + * the platforms via the supplier constructor. + */ + @Deprecated protected abstract Set load(); //FAWE end @@ -81,7 +102,7 @@ public abstract class Category implements RegistryItem { @Override public String toString() { - return getId(); + return id(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Keyed.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Keyed.java index e892ba1f1..dfce5f833 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Keyed.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Keyed.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.registry; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; + /** * Represents an objects that can be added to a registry and referenced by an id which is unique within its registry. */ @@ -28,7 +31,24 @@ public interface Keyed { * The id of this object in the registry. Must be unique, and lowercase. Certain registries (e.g Namespaced ones) may have additional restrictions. * * @return an id + * @deprecated Use {@link #id()} instead. */ - String getId(); + @Deprecated(forRemoval = true, since = "2.11.0") + default String getId() { + return id(); + } + + /** + * The id of this object in the registry. Must be unique and lowercase. Certain registries (e.g namespaced ones) + * may have additional restrictions. + * + * @return an id + * @since 2.11.0 + */ + @NonAbstractForCompatibility(delegateName = "getId", delegateParams = {}) + default String id() { + DeprecationUtil.checkDelegatingOverride(getClass()); + return getId(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/AbstractProperty.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/AbstractProperty.java index e248ad5cb..423e47263 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/AbstractProperty.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/AbstractProperty.java @@ -140,10 +140,10 @@ public abstract class AbstractProperty implements Property { @Override public boolean equals(Object obj) { - if (!(obj instanceof Property)) { + if (!(obj instanceof Property property)) { return false; } - return getName().equals(((Property) obj).getName()); + return getName().equals(property.getName()) && property.getValues().equals(getValues()); } //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java index 8eb6df755..4358a6932 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/CraftScriptContext.java @@ -183,6 +183,7 @@ public class CraftScriptContext extends CraftScriptEnvironment { context.setSession(session); context.setRestricted(!allAllowed); context.setPreferringWildcard(false); + context.setTryLegacy(player.getLimit().ALLOW_LEGACY); return controller.getBlockFactory().parseFromListInput(input, context).stream().findFirst().orElse(null); } @@ -212,6 +213,7 @@ public class CraftScriptContext extends CraftScriptEnvironment { context.setActor(player); context.setWorld(player.getWorld()); context.setSession(session); + context.setTryLegacy(player.getLimit().ALLOW_LEGACY); return controller.getPatternFactory().parseFromInput(list, context); } @@ -230,6 +232,7 @@ public class CraftScriptContext extends CraftScriptEnvironment { context.setWorld(player.getWorld()); context.setSession(session); context.setRestricted(!allBlocksAllowed); + context.setTryLegacy(player.getLimit().ALLOW_LEGACY); return controller.getBlockFactory().parseFromListInput(list, context); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/Placement.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/Placement.java new file mode 100644 index 000000000..3171bc66e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/Placement.java @@ -0,0 +1,52 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.session; + +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; + +//FAWE: not in use (yet) +public record Placement(PlacementType placementType, BlockVector3 offset) { + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + return placementType.getPlacementPosition(selector, actor).add(offset); + } + + public boolean canBeUsedBy(Actor actor) { + return placementType.canBeUsedBy(actor); + } + + public Component getInfo() { + if (offset.equals(BlockVector3.ZERO)) { + return TranslatableComponent.of(placementType.getTranslationKey()); + } else { + return TranslatableComponent.of( + placementType.getTranslationKeyWithOffset(), + TextComponent.of(offset.getX()), + TextComponent.of(offset.getY()), + TextComponent.of(offset.getZ()) + ); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/PlacementType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/PlacementType.java new file mode 100644 index 000000000..90b6ff01e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/PlacementType.java @@ -0,0 +1,119 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.session; + +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Locatable; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.RegionSelector; + +import static com.google.common.base.Preconditions.checkNotNull; + +//FAWE: not in use (yet) +public enum PlacementType { + WORLD("worldedit.toggleplace.world", "worldedit.toggleplace.world-offset") { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + return BlockVector3.ZERO; + } + }, + + PLAYER("worldedit.toggleplace.player", "worldedit.toggleplace.player-offset") { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + if (!canBeUsedBy(actor)) { + throw new IncompleteRegionException(); + } + return ((Locatable) actor).getBlockLocation().toVector().toBlockPoint(); + } + + @Override + public boolean canBeUsedBy(Actor actor) { + checkNotNull(actor); + return actor instanceof Locatable; + } + }, + + HERE(null, null) { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead."); + } + + @Override + public boolean canBeUsedBy(Actor actor) { + return PLAYER.canBeUsedBy(actor); + } + + @Override + public String getTranslationKey() { + throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead."); + } + + @Override + public String getTranslationKeyWithOffset() { + throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead."); + } + }, + + POS1("worldedit.toggleplace.pos1", "worldedit.toggleplace.pos1-offset") { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + return selector.getPrimaryPosition(); + } + }, + + MIN("worldedit.toggleplace.min", "worldedit.toggleplace.min-offset") { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + return selector.getRegion().getMinimumPoint(); + } + }, + + MAX("worldedit.toggleplace.max", "worldedit.toggleplace.max-offset") { + @Override + public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException { + return selector.getRegion().getMaximumPoint(); + } + }; + + private final String translationKey; + private final String translationKeyWithOffset; + + PlacementType(String translationKey, String translationKeyWithOffset) { + this.translationKey = translationKey; + this.translationKeyWithOffset = translationKeyWithOffset; + } + + public abstract BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException; + + public boolean canBeUsedBy(Actor actor) { + return true; + } + + public String getTranslationKey() { + return translationKey; + } + + public String getTranslationKeyWithOffset() { + return translationKeyWithOffset; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java index 2af8232af..5aedae6d9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java @@ -19,7 +19,7 @@ package com.sk89q.worldedit.session.request; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; @@ -119,8 +119,8 @@ public class RequestExtent implements Extent { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return getExtent().setTile(x, y, z, tile); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return getExtent().tile(x, y, z, tile); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java index d117ff328..c10312503 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java @@ -84,7 +84,7 @@ public enum Direction { } Direction(Vector3 vector, int flags, int left, int right) { - this.blockPoint = BlockVector3.at(Math.signum(vector.getX()), Math.signum(vector.getY()), Math.signum(vector.getZ())); + this.blockPoint = BlockVector3.at(Math.signum(vector.x()), Math.signum(vector.y()), Math.signum(vector.z())); this.direction = vector.normalize(); this.flags = flags; this.left = left; @@ -104,27 +104,27 @@ public enum Direction { } public double getX() { - return direction.getX(); + return direction.x(); } public double getY() { - return direction.getY(); + return direction.y(); } public double getZ() { - return direction.getZ(); + return direction.z(); } public int getBlockX() { - return blockPoint.getX(); + return blockPoint.x(); } public int getBlockY() { - return blockPoint.getY(); + return blockPoint.y(); } public int getBlockZ() { - return blockPoint.getZ(); + return blockPoint.z(); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/LocatedBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/LocatedBlock.java index 2ea1d1d59..042f435e0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/LocatedBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/LocatedBlock.java @@ -22,46 +22,38 @@ package com.sk89q.worldedit.util; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; -import java.util.Objects; - import static com.google.common.base.Preconditions.checkNotNull; /** * Represents a block located at some position. */ -public final class LocatedBlock { +public record LocatedBlock(BlockVector3 location, BaseBlock block) { - private final BlockVector3 location; - private final BaseBlock block; - - public LocatedBlock(BlockVector3 location, BaseBlock block) { - this.location = checkNotNull(location); - this.block = checkNotNull(block); + public LocatedBlock { + checkNotNull(location); + checkNotNull(block); } + /** + * Gets the location. + * + * @return The location + * @deprecated This class is now a record. Use {@link #location()} instead. + */ + @Deprecated(forRemoval = true, since = "2.11.0") public BlockVector3 getLocation() { - return location; + return this.location; } + /** + * Gets the block. + * + * @return The block + * @deprecated This class is now a record. Use {@link #block()} instead. + */ + @Deprecated(forRemoval = true, since = "2.11.0") public BaseBlock getBlock() { - return block; - } - - @Override - public int hashCode() { - return Objects.hash(location, block); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (this.getClass() != obj.getClass()) { - return false; - } - LocatedBlock lb = (LocatedBlock) obj; - return Objects.equals(location, lb.location) && Objects.equals(block, lb.block); + return this.block; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Location.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Location.java index 3a3cd6fb8..52c1a3e62 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Location.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Location.java @@ -302,11 +302,11 @@ public class Location extends Vector3Impl { @Override public Location clampY(int min, int max) { checkArgument(min <= max, "minimum cannot be greater than maximum"); - if (getY() < min) { - return new Location(extent, getX(), min, getZ()); + if (y() < min) { + return new Location(extent, x(), min, z()); } - if (getY() > max) { - return new Location(extent, getX(), max, getZ()); + if (y() > max) { + return new Location(extent, x(), max, z()); } return this; @@ -331,13 +331,13 @@ public class Location extends Vector3Impl { return false; } //FAWE start - if (this.getX() != location.getX()) { + if (this.x() != location.x()) { return false; } - if (this.getZ() != location.getZ()) { + if (this.z() != location.z()) { return false; } - if (this.getY() != location.getY()) { + if (this.y() != location.y()) { return false; } return extent.equals(location.extent); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java index f350af03f..7a52770e3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java @@ -112,9 +112,9 @@ public class PropertiesConfiguration extends LocalConfiguration { logFile = getString("log-file", logFile); logFormat = getString("log-format", logFormat); registerHelp = getBool("register-help", registerHelp); - wandItem = getString("wand-item", wandItem).toLowerCase(Locale.ROOT); + wandItem = getString("wand-item", wandItem); try { - wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId(); + wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).id(); } catch (Throwable ignored) { } superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop); @@ -122,9 +122,9 @@ public class PropertiesConfiguration extends LocalConfiguration { useInventory = getBool("use-inventory", useInventory); useInventoryOverride = getBool("use-inventory-override", useInventoryOverride); useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride); - navigationWand = getString("nav-wand-item", navigationWand).toLowerCase(Locale.ROOT); + navigationWand = getString("nav-wand-item", navigationWand); try { - navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId(); + navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).id(); } catch (Throwable ignored) { } navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance); @@ -136,6 +136,14 @@ public class PropertiesConfiguration extends LocalConfiguration { scriptsDir = getString("craftscript-dir", scriptsDir); butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius); butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius); + + //FAWE start + MAX_RADIUS = maxRadius; + MAX_BRUSH_RADIUS = maxBrushRadius; + MAX_SUPER_RADIUS = maxSuperPickaxeSize; + MAX_BUTCHER_RADIUS = butcherMaxRadius; + //FAWE end + allowSymlinks = getBool("allow-symbolic-links", allowSymlinks); serverSideCUI = getBool("server-side-cui", serverSideCUI); extendedYLimit = getBool("extended-y-limit", extendedYLimit); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java index 01444f269..557709931 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java @@ -223,15 +223,15 @@ public class TargetBlock { curDistance += checkDistance; targetPosDouble = offset.add( - targetPosDouble.getX(), - targetPosDouble.getY(), - targetPosDouble.getZ() + targetPosDouble.x(), + targetPosDouble.y(), + targetPosDouble.z() ); targetPos = targetPosDouble.toBlockPoint(); } while (curDistance <= maxDistance - && targetPos.getBlockX() == prevPos.getBlockX() - && targetPos.getBlockY() == prevPos.getBlockY() - && targetPos.getBlockZ() == prevPos.getBlockZ()); + && targetPos.x() == prevPos.x() + && targetPos.y() == prevPos.y() + && targetPos.z() == prevPos.z()); if (curDistance > maxDistance) { return null; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java index cf5c05278..f529b6c5e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java @@ -135,9 +135,9 @@ public final class TreeGenerator { public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException { //FAWE start - perform sanity check on generation location if (editSession - .getBlockType(pos.getX(), pos.getY(), pos.getZ()) + .getBlockType(pos.x(), pos.y(), pos.z()) .getMaterial() - .isAir() && canGenerateOn(editSession.getBlockType(pos.getX(), pos.getY() - 1, pos.getZ()))) { + .isAir() && canGenerateOn(editSession.getBlockType(pos.x(), pos.y() - 1, pos.z()))) { makePineTree(editSession, pos); return true; } @@ -151,7 +151,7 @@ public final class TreeGenerator { //FAWE start - ensure canGenerateOn is called. // chorus plants have to generate starting in the end stone itself, not the air above the ground BlockVector3 down = pos.subtract(0, 1, 0); - if (!canGenerateOn(editSession.getBlockType(down.getX(), down.getY(), down.getZ()))) { + if (!canGenerateOn(editSession.getBlockType(down.x(), down.y(), down.z()))) { return false; } return editSession.getWorld().generateTree(this, editSession, down); @@ -212,9 +212,9 @@ public final class TreeGenerator { public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException { //FAWE start - check for ability for tree to generate on block if (editSession - .getBlockType(pos.getX(), pos.getY(), pos.getZ()) + .getBlockType(pos.x(), pos.y(), pos.z()) .getMaterial() - .isAir() && canGenerateOn(editSession.getBlockType(pos.getX(), pos.getY() - 1, pos.getZ()))) { + .isAir() && canGenerateOn(editSession.getBlockType(pos.x(), pos.y() - 1, pos.z()))) { return editSession.getWorld().generateTree(this, editSession, pos); } return false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/YAMLConfiguration.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/YAMLConfiguration.java index 1a8b0667c..4a5e45713 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/YAMLConfiguration.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/YAMLConfiguration.java @@ -58,7 +58,7 @@ public class YAMLConfiguration extends LocalConfiguration { profile = config.getBoolean("debug", profile); traceUnflushedSessions = config.getBoolean("debugging.trace-unflushed-sessions", traceUnflushedSessions); - wandItem = convertLegacyItem(config.getString("wand-item", wandItem)).toLowerCase(Locale.ROOT); + wandItem = convertLegacyItem(config.getString("wand-item", wandItem)); defaultChangeLimit = Math.max(-1, config.getInt( "limits.max-blocks-changed.default", defaultChangeLimit)); @@ -95,6 +95,13 @@ public class YAMLConfiguration extends LocalConfiguration { butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius)); butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius)); + //FAWE start + MAX_RADIUS = maxRadius; + MAX_BRUSH_RADIUS = maxBrushRadius; + MAX_SUPER_RADIUS = maxSuperPickaxeSize; + MAX_BUTCHER_RADIUS = butcherMaxRadius; + //FAWE end + disallowedBlocks = config.getStringList("limits.disallowed-blocks", Lists.newArrayList(getDefaultDisallowedBlocks())) .stream() .map(s -> s.contains(":") ? s.toLowerCase(Locale.ROOT) : ("minecraft:" + s).toLowerCase(Locale.ROOT)) @@ -123,7 +130,7 @@ public class YAMLConfiguration extends LocalConfiguration { useInventoryCreativeOverride ); - navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand)).toLowerCase(Locale.ROOT); + navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand)); navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance); navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/BlockMap.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/BlockMap.java index 43c175dbc..a17f6a04f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/BlockMap.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/BlockMap.java @@ -85,15 +85,15 @@ public class BlockMap extends AbstractMap { private static final int BITS_6 = mask(6); private static long toGroupKey(BlockVector3 location) { - return ((location.getX() >>> 6) & BITS_20) - | (((location.getZ() >>> 6) & BITS_20) << 20) - | (((location.getY() >>> 8) & BITS_24) << (20 + 20)); + return ((location.x() >>> 6) & BITS_20) + | (((location.z() >>> 6) & BITS_20) << 20) + | (((location.y() >>> 8) & BITS_24) << (20 + 20)); } private static int toInnerKey(BlockVector3 location) { - return (location.getX() & BITS_6) - | ((location.getZ() & BITS_6) << 6) - | ((location.getY() & BITS_8) << (6 + 6)); + return (location.x() & BITS_6) + | ((location.z() & BITS_6) << 6) + | ((location.y() & BITS_8) << (6 + 6)); } private static final long GROUP_X = BITS_20; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/VectorPositionList.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/VectorPositionList.java index 3a2759e67..3e725712d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/VectorPositionList.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/collection/VectorPositionList.java @@ -46,9 +46,9 @@ class VectorPositionList implements PositionList { @Override public void add(BlockVector3 vector) { - delegateX.add(vector.getX()); - delegateY.add(vector.getY()); - delegateZ.add(vector.getZ()); + delegateX.add(vector.x()); + delegateY.add(vector.y()); + delegateZ.add(vector.z()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java index 9b9a9a6e5..416fbeaae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java @@ -19,10 +19,16 @@ package com.sk89q.worldedit.util.gson; +import com.fastasyncworldedit.core.util.gson.BaseItemAdapter; +import com.fastasyncworldedit.core.util.gson.ItemTypeAdapter; +import com.fastasyncworldedit.core.util.gson.RegionSelectorAdapter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.world.item.ItemType; /** * Utility methods for Google's GSON library. @@ -41,6 +47,11 @@ public final class GsonUtil { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter()); gsonBuilder.registerTypeAdapter(BlockVector3.class, new BlockVectorAdapter()); + //FAWE start + gsonBuilder.registerTypeAdapter(RegionSelector.class, new RegionSelectorAdapter()); + gsonBuilder.registerTypeAdapter(ItemType.class, new ItemTypeAdapter()); + gsonBuilder.registerTypeAdapter(BaseItem.class, new BaseItemAdapter()); + //FAWE end return gsonBuilder; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java index 585eaa00e..47f17781f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java @@ -19,11 +19,16 @@ package com.sk89q.worldedit.util.io; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.IOException; import java.io.InputStream; public class ForwardSeekableInputStream extends InputStream { + private static final Logger LOGGER = LogManager.getLogger(); + protected InputStream parent; protected long position = 0; @@ -60,7 +65,7 @@ public class ForwardSeekableInputStream extends InputStream { @Override public int read(byte[] b, int off, int len) throws IOException { - int read = super.read(b, off, len); + int read = parent.read(b, off, len); position += read; return read; } @@ -86,6 +91,7 @@ public class ForwardSeekableInputStream extends InputStream { public void seek(long n) throws IOException { long diff = n - position; + LOGGER.error("Seek to {} from {} using {}", n, position, diff); if (diff < 0) { throw new IOException("Can't seek backwards"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java index a5c9fdced..d133eb54e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java @@ -357,7 +357,7 @@ public class HttpRequest implements Closeable { */ public static URL url(String url) { try { - return new URL(url); + return URI.create(url).toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } @@ -371,13 +371,7 @@ public class HttpRequest implements Closeable { */ private static URL reformat(URL existing) { try { - URL url = new URL(existing.toString()); - URI uri = new URI( - url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), - url.getPath(), url.getQuery(), url.getRef() - ); - url = uri.toURL(); - return url; + return existing.toURI().toURL(); } catch (MalformedURLException | URISyntaxException e) { return existing; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java index 680dbed0d..152dcfea3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java @@ -83,4 +83,26 @@ public final class ActorCallbackPaste { .buildAndExec(Pasters.getExecutor()); } + + /** + * Submit data to a pastebin service and inform the sender of + * success or failure. + * + * @param supervisor The supervisor instance + * @param sender The sender + * @param content The content + * @param pasteMetadata The paste metadata + * @param successMessage The message builder, given the URL as an arg + */ + public static void pastebin(Supervisor supervisor, final Actor sender, String content, PasteMetadata pasteMetadata, final TranslatableComponent.Builder successMessage) { + Callable task = paster.paste(content, pasteMetadata); + + AsyncCommandBuilder.wrap(task, sender) + .registerWithSupervisor(supervisor, "Submitting content to a pastebin service.") + .setDelayMessage(TranslatableComponent.of("worldedit.pastebin.uploading")) + .onSuccess((String) null, url -> sender.printInfo(successMessage.args(TextComponent.of(url.toString())).build())) + .onFailure("Failed to submit paste", null) + .buildAndExec(Pasters.getExecutor()); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java index f9bf84375..1decfd384 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java @@ -24,6 +24,7 @@ import com.google.gson.reflect.TypeToken; import com.sk89q.worldedit.util.net.HttpRequest; import java.io.IOException; +import java.net.URI; import java.net.URL; import java.util.Map; import java.util.concurrent.Callable; @@ -33,23 +34,38 @@ public class EngineHubPaste implements Paster { private static final Gson GSON = new Gson(); @Override - public Callable paste(String content) { - return new PasteTask(content); + public Callable paste(String content, PasteMetadata metadata) { + return new PasteTask(content, metadata); } private static final class PasteTask implements Callable { private final String content; + private final PasteMetadata metadata; - private PasteTask(String content) { + private PasteTask(String content, PasteMetadata metadata) { this.content = content; + this.metadata = metadata; } @Override public URL call() throws IOException, InterruptedException { URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste"); - SignedPasteResponse response = GSON.fromJson(HttpRequest.get(initialUrl) + HttpRequest requestBuilder = HttpRequest.get(initialUrl); + + requestBuilder.header("x-paste-meta-from", "EngineHub"); + if (metadata.name != null) { + requestBuilder.header("x-paste-meta-name", metadata.name); + } + if (metadata.author != null) { + requestBuilder.header("x-paste-meta-author", metadata.author); + } + if (metadata.extension != null) { + requestBuilder.header("x-paste-meta-extension", metadata.extension); + } + + SignedPasteResponse response = GSON.fromJson(requestBuilder .execute() .expectResponseCode(200) .returnContent() @@ -68,7 +84,7 @@ public class EngineHubPaste implements Paster { .execute() .expectResponseCode(200, 204); - return new URL(response.viewUrl); + return URI.create(response.viewUrl).toURL(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java new file mode 100644 index 000000000..5654e6ae5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java @@ -0,0 +1,26 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.paste; + +public class PasteMetadata { + public String name; + public String extension; + public String author; +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java index 0b7652b91..ccd5780b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java @@ -24,6 +24,10 @@ import java.util.concurrent.Callable; public interface Paster { - Callable paste(String content); + default Callable paste(String content) { + return paste(content, new PasteMetadata()); + } + + Callable paste(String content, PasteMetadata metadata); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/report/DataReport.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/report/DataReport.java index 8a18f07b3..62e83a7b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/report/DataReport.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/report/DataReport.java @@ -168,16 +168,7 @@ public class DataReport implements Report { } } - private static class Line { - - private final String key; - private final String value; - - public Line(String key, String value) { - this.key = key; - this.value = value; - } - + private record Line(String key, String value) { } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java index fcf0bd661..515d4d53b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java @@ -82,21 +82,22 @@ public class FutureForwardingTask extends AbstractTask { return future.get(timeout, unit); } + // TODO: consider deprecating in favor of Future.State? @Override - public State getState() { + public Task.State getState() { if (isCancelled()) { - return State.CANCELLED; + return Task.State.CANCELLED; } else if (isDone()) { try { get(); - return State.SUCCEEDED; + return Task.State.SUCCEEDED; } catch (InterruptedException e) { - return State.CANCELLED; + return Task.State.CANCELLED; } catch (ExecutionException e) { - return State.FAILED; + return Task.State.FAILED; } } else { - return State.RUNNING; + return Task.State.RUNNING; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/DataFixer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/DataFixer.java index 5b69ddff0..414190a98 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/DataFixer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/DataFixer.java @@ -20,8 +20,7 @@ package com.sk89q.worldedit.world; import com.google.common.annotations.Beta; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import org.enginehub.linbus.tree.LinCompoundTag; /** * This entire class is subject to heavy changes. Do not use this as API. @@ -41,15 +40,12 @@ public interface DataFixer { private FixTypes() { } - //FAWE start - BinaryTag - public static FixType CHUNK = new FixType<>(); - public static FixType BLOCK_ENTITY = new FixType<>(); - public static FixType ENTITY = new FixType<>(); - //FAWE end - public static FixType BLOCK_STATE = new FixType<>(); - public static FixType BIOME = new FixType<>(); - public static FixType ITEM_TYPE = new FixType<>(); - + public static final FixType CHUNK = new FixType<>(); + public static final FixType BLOCK_ENTITY = new FixType<>(); + public static final FixType ENTITY = new FixType<>(); + public static final FixType BLOCK_STATE = new FixType<>(); + public static final FixType BIOME = new FixType<>(); + public static final FixType ITEM_TYPE = new FixType<>(); } default T fixUp(FixType type, T original) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java index a85868685..e1c5d6de0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NbtValued.java @@ -23,7 +23,7 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.internal.util.DeprecationUtil; import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; @@ -66,7 +66,7 @@ public interface NbtValued { @Deprecated @Nullable default CompoundTag getNbtData() { - CompoundBinaryTag tag = getNbt(); + LinCompoundTag tag = getNbt(); return tag == null ? null : new CompoundTag(tag); } @@ -78,7 +78,7 @@ public interface NbtValued { */ @Deprecated default void setNbtData(@Nullable CompoundTag nbtData) { - setNbtReference(nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag)); + setNbtReference(nbtData == null ? null : LazyReference.from(nbtData::toLinTag)); } /** @@ -96,11 +96,12 @@ public interface NbtValued { delegateParams = {} ) @Nullable - default LazyReference getNbtReference() { + default LazyReference getNbtReference() { DeprecationUtil.checkDelegatingOverride(getClass()); + @SuppressWarnings("deprecation") CompoundTag nbtData = getNbtData(); - return nbtData == null ? null : LazyReference.from(nbtData::asBinaryTag); + return nbtData == null ? null : LazyReference.from(nbtData::toLinTag); } /** @@ -109,8 +110,8 @@ public interface NbtValued { * @return compound tag, or null */ @Nullable - default CompoundBinaryTag getNbt() { - LazyReference ref = getNbtReference(); + default LinCompoundTag getNbt() { + LazyReference ref = getNbtReference(); return ref == null ? null : ref.getValue(); } @@ -119,11 +120,12 @@ public interface NbtValued { * * @param nbtData NBT data, or null if no data */ + @SuppressWarnings("deprecation") @NonAbstractForCompatibility( delegateName = "setNbtData", delegateParams = {CompoundTag.class} ) - default void setNbtReference(@Nullable LazyReference nbtData) { + default void setNbtReference(@Nullable LazyReference nbtData) { DeprecationUtil.checkDelegatingOverride(getClass()); setNbtData(nbtData == null ? null : new CompoundTag(nbtData.getValue())); @@ -134,7 +136,7 @@ public interface NbtValued { * * @param nbtData NBT data, or null if no data */ - default void setNbt(@Nullable CompoundBinaryTag nbtData) { + default void setNbt(@Nullable LinCompoundTag nbtData) { setNbtReference(nbtData == null ? null : LazyReference.computed(nbtData)); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java index 908e0bac6..d3ad7bfd9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java @@ -19,11 +19,11 @@ package com.sk89q.worldedit.world; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.blocks.NullChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.google.common.collect.ImmutableSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -78,7 +78,7 @@ public class NullWorld extends AbstractWorld { //FAWE end @Override - public String getId() { + public String id() { return "null"; } @@ -184,7 +184,7 @@ public class NullWorld extends AbstractWorld { @Override public BlockState getBlock(BlockVector3 position) { - return this.getBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return this.getBlock(position.x(), position.y(), position.z()); } @Override @@ -204,7 +204,7 @@ public class NullWorld extends AbstractWorld { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java index 79822a934..553792599 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java @@ -419,7 +419,7 @@ public interface World extends Extent, Keyed, IChunkCache { } @Override - default String getId() { + default String id() { return getName().replace(" ", "_").toLowerCase(Locale.ROOT); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategories.java new file mode 100644 index 000000000..ee1cca1c0 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategories.java @@ -0,0 +1,112 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.world.biome; + +/** + * Stores a list of common {@link BiomeCategory BiomeCategories}. + * + * @see BiomeCategory + */ +@SuppressWarnings("unused") +public final class BiomeCategories { + public static final BiomeCategory ALLOWS_SURFACE_SLIME_SPAWNS = get("minecraft:allows_surface_slime_spawns"); + public static final BiomeCategory ALLOWS_TROPICAL_FISH_SPAWNS_AT_ANY_HEIGHT = get("minecraft:allows_tropical_fish_spawns_at_any_height"); + public static final BiomeCategory HAS_CLOSER_WATER_FOG = get("minecraft:has_closer_water_fog"); + public static final BiomeCategory HAS_STRUCTURE_ANCIENT_CITY = get("minecraft:has_structure/ancient_city"); + public static final BiomeCategory HAS_STRUCTURE_BASTION_REMNANT = get("minecraft:has_structure/bastion_remnant"); + public static final BiomeCategory HAS_STRUCTURE_BURIED_TREASURE = get("minecraft:has_structure/buried_treasure"); + public static final BiomeCategory HAS_STRUCTURE_DESERT_PYRAMID = get("minecraft:has_structure/desert_pyramid"); + public static final BiomeCategory HAS_STRUCTURE_END_CITY = get("minecraft:has_structure/end_city"); + public static final BiomeCategory HAS_STRUCTURE_IGLOO = get("minecraft:has_structure/igloo"); + public static final BiomeCategory HAS_STRUCTURE_JUNGLE_TEMPLE = get("minecraft:has_structure/jungle_temple"); + public static final BiomeCategory HAS_STRUCTURE_MINESHAFT = get("minecraft:has_structure/mineshaft"); + public static final BiomeCategory HAS_STRUCTURE_MINESHAFT_MESA = get("minecraft:has_structure/mineshaft_mesa"); + public static final BiomeCategory HAS_STRUCTURE_NETHER_FORTRESS = get("minecraft:has_structure/nether_fortress"); + public static final BiomeCategory HAS_STRUCTURE_NETHER_FOSSIL = get("minecraft:has_structure/nether_fossil"); + public static final BiomeCategory HAS_STRUCTURE_OCEAN_MONUMENT = get("minecraft:has_structure/ocean_monument"); + public static final BiomeCategory HAS_STRUCTURE_OCEAN_RUIN_COLD = get("minecraft:has_structure/ocean_ruin_cold"); + public static final BiomeCategory HAS_STRUCTURE_OCEAN_RUIN_WARM = get("minecraft:has_structure/ocean_ruin_warm"); + public static final BiomeCategory HAS_STRUCTURE_PILLAGER_OUTPOST = get("minecraft:has_structure/pillager_outpost"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_DESERT = get("minecraft:has_structure/ruined_portal_desert"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_JUNGLE = get("minecraft:has_structure/ruined_portal_jungle"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_MOUNTAIN = get("minecraft:has_structure/ruined_portal_mountain"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_NETHER = get("minecraft:has_structure/ruined_portal_nether"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_OCEAN = get("minecraft:has_structure/ruined_portal_ocean"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_STANDARD = get("minecraft:has_structure/ruined_portal_standard"); + public static final BiomeCategory HAS_STRUCTURE_RUINED_PORTAL_SWAMP = get("minecraft:has_structure/ruined_portal_swamp"); + public static final BiomeCategory HAS_STRUCTURE_SHIPWRECK = get("minecraft:has_structure/shipwreck"); + public static final BiomeCategory HAS_STRUCTURE_SHIPWRECK_BEACHED = get("minecraft:has_structure/shipwreck_beached"); + public static final BiomeCategory HAS_STRUCTURE_STRONGHOLD = get("minecraft:has_structure/stronghold"); + public static final BiomeCategory HAS_STRUCTURE_SWAMP_HUT = get("minecraft:has_structure/swamp_hut"); + public static final BiomeCategory HAS_STRUCTURE_TRAIL_RUINS = get("minecraft:has_structure/trail_ruins"); + public static final BiomeCategory HAS_STRUCTURE_VILLAGE_DESERT = get("minecraft:has_structure/village_desert"); + public static final BiomeCategory HAS_STRUCTURE_VILLAGE_PLAINS = get("minecraft:has_structure/village_plains"); + public static final BiomeCategory HAS_STRUCTURE_VILLAGE_SAVANNA = get("minecraft:has_structure/village_savanna"); + public static final BiomeCategory HAS_STRUCTURE_VILLAGE_SNOWY = get("minecraft:has_structure/village_snowy"); + public static final BiomeCategory HAS_STRUCTURE_VILLAGE_TAIGA = get("minecraft:has_structure/village_taiga"); + public static final BiomeCategory HAS_STRUCTURE_WOODLAND_MANSION = get("minecraft:has_structure/woodland_mansion"); + public static final BiomeCategory INCREASED_FIRE_BURNOUT = get("minecraft:increased_fire_burnout"); + public static final BiomeCategory IS_BADLANDS = get("minecraft:is_badlands"); + public static final BiomeCategory IS_BEACH = get("minecraft:is_beach"); + public static final BiomeCategory IS_DEEP_OCEAN = get("minecraft:is_deep_ocean"); + public static final BiomeCategory IS_END = get("minecraft:is_end"); + public static final BiomeCategory IS_FOREST = get("minecraft:is_forest"); + public static final BiomeCategory IS_HILL = get("minecraft:is_hill"); + public static final BiomeCategory IS_JUNGLE = get("minecraft:is_jungle"); + public static final BiomeCategory IS_MOUNTAIN = get("minecraft:is_mountain"); + public static final BiomeCategory IS_NETHER = get("minecraft:is_nether"); + public static final BiomeCategory IS_OCEAN = get("minecraft:is_ocean"); + public static final BiomeCategory IS_OVERWORLD = get("minecraft:is_overworld"); + public static final BiomeCategory IS_RIVER = get("minecraft:is_river"); + public static final BiomeCategory IS_SAVANNA = get("minecraft:is_savanna"); + public static final BiomeCategory IS_TAIGA = get("minecraft:is_taiga"); + public static final BiomeCategory MINESHAFT_BLOCKING = get("minecraft:mineshaft_blocking"); + public static final BiomeCategory MORE_FREQUENT_DROWNED_SPAWNS = get("minecraft:more_frequent_drowned_spawns"); + public static final BiomeCategory PLAYS_UNDERWATER_MUSIC = get("minecraft:plays_underwater_music"); + public static final BiomeCategory POLAR_BEARS_SPAWN_ON_ALTERNATE_BLOCKS = get("minecraft:polar_bears_spawn_on_alternate_blocks"); + public static final BiomeCategory PRODUCES_CORALS_FROM_BONEMEAL = get("minecraft:produces_corals_from_bonemeal"); + public static final BiomeCategory REDUCE_WATER_AMBIENT_SPAWNS = get("minecraft:reduce_water_ambient_spawns"); + public static final BiomeCategory REQUIRED_OCEAN_MONUMENT_SURROUNDING = get("minecraft:required_ocean_monument_surrounding"); + public static final BiomeCategory SNOW_GOLEM_MELTS = get("minecraft:snow_golem_melts"); + public static final BiomeCategory SPAWNS_COLD_VARIANT_FROGS = get("minecraft:spawns_cold_variant_frogs"); + public static final BiomeCategory SPAWNS_GOLD_RABBITS = get("minecraft:spawns_gold_rabbits"); + public static final BiomeCategory SPAWNS_SNOW_FOXES = get("minecraft:spawns_snow_foxes"); + public static final BiomeCategory SPAWNS_WARM_VARIANT_FROGS = get("minecraft:spawns_warm_variant_frogs"); + public static final BiomeCategory SPAWNS_WHITE_RABBITS = get("minecraft:spawns_white_rabbits"); + public static final BiomeCategory STRONGHOLD_BIASED_TO = get("minecraft:stronghold_biased_to"); + public static final BiomeCategory WATER_ON_MAP_OUTLINES = get("minecraft:water_on_map_outlines"); + public static final BiomeCategory WITHOUT_PATROL_SPAWNS = get("minecraft:without_patrol_spawns"); + public static final BiomeCategory WITHOUT_WANDERING_TRADER_SPAWNS = get("minecraft:without_wandering_trader_spawns"); + public static final BiomeCategory WITHOUT_ZOMBIE_SIEGES = get("minecraft:without_zombie_sieges"); + + private BiomeCategories() { + } + + /** + * Gets the {@link BiomeCategory} associated with the given id. + */ + public static BiomeCategory get(String id) { + BiomeCategory entry = BiomeCategory.REGISTRY.get(id); + if (entry == null) { + return new BiomeCategory(id); + } + return entry; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategory.java new file mode 100644 index 000000000..a51a86823 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeCategory.java @@ -0,0 +1,49 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.world.biome; + +import com.sk89q.worldedit.registry.Category; +import com.sk89q.worldedit.registry.Keyed; +import com.sk89q.worldedit.registry.NamespacedRegistry; + +import java.util.Set; +import java.util.function.Supplier; + +/** + * A category of biomes. + */ +public class BiomeCategory extends Category implements Keyed { + + public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("biome tag", true); + + public BiomeCategory(final String id) { + super(id); + } + + public BiomeCategory(final String id, final Supplier> contentSupplier) { + super(id, contentSupplier); + } + + @Override + protected Set load() { + return Set.of(); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeType.java index e8501da69..d49289093 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeType.java @@ -28,21 +28,32 @@ import com.sk89q.worldedit.registry.NamespacedRegistry; /** * All the types of biomes in the game. */ -//FAWE start - RegistryItem +//FAWE start - RegistryItem + not a record (legacyId + internalId need mutability) public class BiomeType implements RegistryItem, Keyed, BiomePattern { //FAWE end public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("biome type", true); + //FAWE start private final String id; private int legacyId = -1; private int internalId; - //FAWE start public BiomeType(String id) { this.id = id; } + /** + * Gets the ID of this biome. + * + * @return The id + * @since 2.11.0 + */ + @Override + public String id() { + return this.id; + } + public int getLegacyId() { return legacyId; } @@ -60,13 +71,14 @@ public class BiomeType implements RegistryItem, Keyed, BiomePattern { public int getInternalId() { return internalId; } - //FAWE end /** * Gets the ID of this biome. * * @return The id + * @deprecated use {@link #id()} */ + @Deprecated(forRemoval = true, since = "2.11.0") @Override public String getId() { return this.id; @@ -74,20 +86,19 @@ public class BiomeType implements RegistryItem, Keyed, BiomePattern { @Override public String toString() { - return getId(); + return id(); } @Override public int hashCode() { - //FAWE start - internalId > hashCode - return this.internalId; // stop changing this - //FAWE end + return this.internalId; // stop changing this (ok) } @Override public boolean equals(Object obj) { return obj instanceof BiomeType && this.id.equals(((BiomeType) obj).id); } + //FAWE end @Override public BiomeType applyBiome(BlockVector3 position) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeTypes.java index 6fe08a295..e8a5e144a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/biome/BiomeTypes.java @@ -291,7 +291,7 @@ public final class BiomeTypes { } public static BiomeType register(final BiomeType biome) { - return BiomeType.REGISTRY.register(biome.getId(), biome); + return BiomeType.REGISTRY.register(biome.id(), biome); } public static BiomeType getLegacy(int legacyId) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index 9828c9069..ea54b1c7a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -19,9 +19,9 @@ package com.sk89q.worldedit.world.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.extent.Extent; @@ -29,13 +29,13 @@ import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.TagStringIO; import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.LegacyMapper; +import org.enginehub.linbus.format.snbt.LinStringIO; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nullable; -import java.io.IOException; import java.util.Map; import java.util.Objects; @@ -54,7 +54,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { private final BlockState blockState; @Nullable - private final LazyReference nbtData; + private final LazyReference nbtData; //FAWE start @@ -93,7 +93,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { */ @Deprecated public BaseBlock(BlockState state, CompoundTag nbtData) { - this(state, LazyReference.from(checkNotNull(nbtData)::asBinaryTag)); + this(state, LazyReference.from(checkNotNull(nbtData)::toLinTag)); } //FAWE end @@ -104,7 +104,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { * @param state The block state * @param nbtData NBT data, which must be provided */ - protected BaseBlock(BlockState state, LazyReference nbtData) { + protected BaseBlock(BlockState state, LazyReference nbtData) { checkNotNull(nbtData); this.blockState = state; this.nbtData = nbtData; @@ -165,21 +165,21 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public String getNbtId() { - LazyReference nbtData = this.nbtData; + LazyReference nbtData = this.nbtData; if (nbtData == null) { return ""; } - return nbtData.getValue().getString("id"); + return nbtData.getValue().getTag("id", LinTagType.stringTag()).value(); } @Nullable @Override - public LazyReference getNbtReference() { + public LazyReference getNbtReference() { return this.nbtData; } @Override - public void setNbtReference(@Nullable LazyReference nbtData) { + public void setNbtReference(@Nullable LazyReference nbtData) { throw new UnsupportedOperationException("This class is immutable."); } @@ -244,7 +244,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { } @Override - public BaseBlock toBaseBlock(LazyReference compoundTag) { + public BaseBlock toBaseBlock(LazyReference compoundTag) { if (compoundTag == null) { return this.blockState.toBaseBlock(); } else if (compoundTag == this.nbtData) { @@ -263,15 +263,15 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public void applyTileEntity(OutputExtent output, int x, int y, int z) { - CompoundTag nbt = getNbtData(); + LinCompoundTag nbt = getNbt(); if (nbt != null) { - output.setTile(x, y, z, nbt); + output.tile(x, y, z, FaweCompoundTag.of(nbt)); } } @Override public BaseBlock withPropertyId(int propertyId) { - return getBlockType().withPropertyId(propertyId).toBaseBlock(getNbtData()); + return getBlockType().withPropertyId(propertyId).toBaseBlock(getNbtReference()); } @Override @@ -286,7 +286,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public BaseBlock with(PropertyKey property, V value) { - return toImmutableState().with(property, value).toBaseBlock(getNbtData()); + return toImmutableState().with(property, value).toBaseBlock(getNbtReference()); } @Override @@ -300,20 +300,20 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public int hashCode() { - return getOrdinal(); + int ret = getOrdinal() << 3; + LinCompoundTag nbtData = getNbt(); + if (nbtData != null) { + ret += nbtData.hashCode(); + } + return ret; } //FAWE end @Override public String toString() { String nbtString = ""; - CompoundBinaryTag nbtData = getNbt(); if (nbtData != null) { - try { - nbtString = TagStringIO.get().asString(nbtData); - } catch (IOException e) { - WorldEdit.logger.error("Failed to serialize NBT of Block", e); - } + nbtString = LinStringIO.writeToString(nbtData.getValue()); } return blockState.getAsString() + nbtString; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java index 47905dcd4..7d09d509e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java @@ -33,8 +33,10 @@ public final class BlockCategories { public static final BlockCategory ANCIENT_CITY_REPLACEABLE = get("minecraft:ancient_city_replaceable"); public static final BlockCategory ANIMALS_SPAWNABLE_ON = get("minecraft:animals_spawnable_on"); public static final BlockCategory ANVIL = get("minecraft:anvil"); + public static final BlockCategory ARMADILLO_SPAWNABLE_ON = get("minecraft:armadillo_spawnable_on"); public static final BlockCategory AXOLOTLS_SPAWNABLE_ON = get("minecraft:axolotls_spawnable_on"); public static final BlockCategory AZALEA_GROWS_ON = get("minecraft:azalea_grows_on"); + public static final BlockCategory BADLANDS_TERRACOTTA = get("minecraft:badlands_terracotta"); public static final BlockCategory AZALEA_ROOT_REPLACEABLE = get("minecraft:azalea_root_replaceable"); public static final BlockCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final BlockCategory BAMBOO_PLANTABLE_ON = get("minecraft:bamboo_plantable_on"); @@ -48,6 +50,7 @@ public final class BlockCategories { public static final BlockCategory BIG_DRIPLEAF_PLACEABLE = get("minecraft:big_dripleaf_placeable"); public static final BlockCategory BIRCH_LOGS = get("minecraft:birch_logs"); public static final BlockCategory BUTTONS = get("minecraft:buttons"); + public static final BlockCategory CAMEL_SAND_STEP_SOUND_BLOCKS = get("minecraft:camel_sand_step_sound_blocks"); public static final BlockCategory CAMPFIRES = get("minecraft:campfires"); public static final BlockCategory CANDLE_CAKES = get("minecraft:candle_cakes"); public static final BlockCategory CANDLES = get("minecraft:candles"); @@ -60,6 +63,7 @@ public final class BlockCategories { public static final BlockCategory COAL_ORES = get("minecraft:coal_ores"); public static final BlockCategory COMBINATION_STEP_SOUND_BLOCKS = get("minecraft:combination_step_sound_blocks"); public static final BlockCategory COMPLETES_FIND_TREE_TUTORIAL = get("minecraft:completes_find_tree_tutorial"); + public static final BlockCategory CONCRETE_POWDER = get("minecraft:concrete_powder"); public static final BlockCategory CONVERTABLE_TO_MUD = get("minecraft:convertable_to_mud"); public static final BlockCategory COPPER_ORES = get("minecraft:copper_ores"); public static final BlockCategory CORAL_BLOCKS = get("minecraft:coral_blocks"); @@ -76,6 +80,7 @@ public final class BlockCategories { public static final BlockCategory DIRT = get("minecraft:dirt"); @Deprecated public static final BlockCategory DIRT_LIKE = get("minecraft:dirt_like"); + public static final BlockCategory DOES_NOT_BLOCK_HOPPERS = get("minecraft:does_not_block_hoppers"); public static final BlockCategory DOORS = get("minecraft:doors"); public static final BlockCategory DRAGON_IMMUNE = get("minecraft:dragon_immune"); public static final BlockCategory DRAGON_TRANSPARENT = get("minecraft:dragon_transparent"); @@ -101,6 +106,12 @@ public final class BlockCategories { public static final BlockCategory HOGLIN_REPELLENTS = get("minecraft:hoglin_repellents"); public static final BlockCategory ICE = get("minecraft:ice"); public static final BlockCategory IMPERMEABLE = get("minecraft:impermeable"); + public static final BlockCategory INCORRECT_FOR_DIAMOND_TOOL = get("minecraft:incorrect_for_diamond_tool"); + public static final BlockCategory INCORRECT_FOR_GOLD_TOOL = get("minecraft:incorrect_for_gold_tool"); + public static final BlockCategory INCORRECT_FOR_IRON_TOOL = get("minecraft:incorrect_for_iron_tool"); + public static final BlockCategory INCORRECT_FOR_NETHERITE_TOOL = get("minecraft:incorrect_for_netherite_tool"); + public static final BlockCategory INCORRECT_FOR_STONE_TOOL = get("minecraft:incorrect_for_stone_tool"); + public static final BlockCategory INCORRECT_FOR_WOODEN_TOOL = get("minecraft:incorrect_for_wooden_tool"); public static final BlockCategory INFINIBURN_END = get("minecraft:infiniburn_end"); public static final BlockCategory INFINIBURN_NETHER = get("minecraft:infiniburn_nether"); public static final BlockCategory INFINIBURN_OVERWORLD = get("minecraft:infiniburn_overworld"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index f08675fc5..0be6d43c8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.world.block; import com.fastasyncworldedit.core.command.SuggestInputParseException; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.fastasyncworldedit.core.util.MutableCharSequence; @@ -45,8 +46,8 @@ import com.sk89q.worldedit.registry.state.AbstractProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.TextComponent; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.registry.BlockMaterial; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -154,7 +155,7 @@ public class BlockState implements BlockStateHolder, Pattern { String input = key.toString(); throw new SuggestInputParseException(Caption.of("fawe.error.invalid-block-type", TextComponent.of(input)), () -> Stream.of( BlockTypesCache.values) - .map(BlockType::getId) + .map(BlockType::id) .filter(id -> StringMan.blockStateMatches(input, id)) .sorted(StringMan.blockStateComparator(input)) .collect(Collectors.toList()) @@ -178,9 +179,18 @@ public class BlockState implements BlockStateHolder, Pattern { String name = property.getName(); charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1); - int index = charSequence.length() <= 0 ? -1 : property.getIndexFor(charSequence); - if (index != -1) { - return type.withPropertyId(index); + try { + int index = charSequence.length() <= 0 ? -1 : property.getIndexFor(charSequence); + if (index != -1) { + return type.withPropertyId(index); + } + } catch (Exception e) { + throw new InputParseException(Caption.of( + "fawe.error.invalid-block-state-property", + TextComponent.of(charSequence.toString()), + TextComponent.of(name), + TextComponent.of(state) + ), e); } } int stateId; @@ -200,7 +210,17 @@ public class BlockState implements BlockStateHolder, Pattern { case ',': { charSequence.setSubstring(last, i); if (property != null) { - int index = property.getIndexFor(charSequence); + int index; + try { + index = property.getIndexFor(charSequence); + } catch (Exception e) { + throw new InputParseException(Caption.of( + "fawe.error.invalid-block-state-property", + TextComponent.of(charSequence.toString()), + TextComponent.of(property.getName()), + TextComponent.of(state) + ), e); + } if (index == -1) { throw SuggestInputParseException.of(charSequence.toString(), (List) property.getValues()); } @@ -292,6 +312,11 @@ public class BlockState implements BlockStateHolder, Pattern { return newState != this.getInternalId() ? type.withStateId(newState) : this; } catch (ClassCastException e) { throw new IllegalArgumentException("Property not found: " + property); + } catch (Exception e) { + throw new UnsupportedOperationException( + "Error resolving property " + property.getName() + " for block type " + getBlockType().id() + "(nullable) value " + value, + e + ); } } @@ -302,6 +327,11 @@ public class BlockState implements BlockStateHolder, Pattern { return (V) ap.getValue(this.getInternalId()); } catch (ClassCastException e) { throw new IllegalArgumentException("Property not found: " + property); + } catch (Exception e) { + throw new UnsupportedOperationException( + "Error resolving property " + property.getName() + " for blocktype " + getBlockType().id(), + e + ); } } @@ -317,6 +347,11 @@ public class BlockState implements BlockStateHolder, Pattern { return newState != this.getInternalId() ? type.withStateId(newState) : this; } catch (ClassCastException e) { throw new IllegalArgumentException("Property not found: " + property); + } catch (Exception e) { + throw new UnsupportedOperationException( + "Error resolving property " + property.getName() + " for block type " + getBlockType().id() + "(nullable) value " + value, + e + ); } } @@ -331,7 +366,7 @@ public class BlockState implements BlockStateHolder, Pattern { BlockState newState = this; for (Property prop : ot.getProperties()) { PropertyKey key = prop.getKey(); - if (blockType.hasProperty(key)) { + if (blockType.hasProperty(prop)) { newState = newState.with(key, other.getState(key)); } } @@ -401,7 +436,7 @@ public class BlockState implements BlockStateHolder, Pattern { //FAWE end @Override - public BaseBlock toBaseBlock(LazyReference compoundTag) { + public BaseBlock toBaseBlock(LazyReference compoundTag) { if (compoundTag == null) { return toBaseBlock(); } @@ -457,6 +492,12 @@ public class BlockState implements BlockStateHolder, Pattern { public BaseBlock toBaseBlock(ITileInput input, int x, int y, int z) { return compoundInput.get(this, input, x, y, z); } + + @Override + public BaseBlock toBaseBlock(final IBlocks blocks, final int x, final int y, final int z) { + return compoundInput.get(this, blocks, x, y, z); + } + //FAWE end @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java index 5f6667a13..808f8f23f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.block; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.sk89q.jnbt.CompoundTag; @@ -30,8 +31,8 @@ import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.registry.BlockMaterial; +import org.enginehub.linbus.tree.LinCompoundTag; import java.util.Locale; import java.util.Map; @@ -158,7 +159,7 @@ public interface BlockStateHolder> extends TileEnt */ @Deprecated default BaseBlock toBaseBlock(CompoundTag compoundTag) { - return toBaseBlock(compoundTag == null ? null : LazyReference.from(compoundTag::asBinaryTag)); + return toBaseBlock(compoundTag == null ? null : LazyReference.from(compoundTag::toLinTag)); } /** @@ -169,11 +170,12 @@ public interface BlockStateHolder> extends TileEnt * This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} * for details */ + @SuppressWarnings("deprecation") @NonAbstractForCompatibility( delegateName = "toBaseBlock", delegateParams = {CompoundTag.class} ) - default BaseBlock toBaseBlock(LazyReference compoundTag) { + default BaseBlock toBaseBlock(LazyReference compoundTag) { DeprecationUtil.checkDelegatingOverride(getClass()); return toBaseBlock(compoundTag == null ? null : new CompoundTag(compoundTag.getValue())); @@ -185,7 +187,7 @@ public interface BlockStateHolder> extends TileEnt * @param compoundTag The NBT Data to apply * @return The BaseBlock */ - default BaseBlock toBaseBlock(CompoundBinaryTag compoundTag) { + default BaseBlock toBaseBlock(LinCompoundTag compoundTag) { return toBaseBlock(compoundTag == null ? null : LazyReference.computed(compoundTag)); } @@ -200,18 +202,22 @@ public interface BlockStateHolder> extends TileEnt default BaseBlock toBaseBlock(ITileInput input, int x, int y, int z) { throw new UnsupportedOperationException("State is immutable"); } + + default BaseBlock toBaseBlock(IBlocks blocks, int x, int y, int z) { + throw new UnsupportedOperationException("State is immutable"); + } //FAWE end default String getAsString() { if (getStates().isEmpty()) { - return this.getBlockType().getId(); + return this.getBlockType().id(); } else { String properties = getStates().entrySet().stream() .map(entry -> entry.getKey().getName() + "=" + entry.getValue().toString().toLowerCase(Locale.ROOT)) .collect(Collectors.joining(",")); - return this.getBlockType().getId() + "[" + properties + "]"; + return this.getBlockType().id() + "[" + properties + "]"; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 7762ee532..4592c7ce2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -60,6 +60,7 @@ public class BlockType implements Keyed, Pattern { private static final Logger LOGGER = LogManagerCompat.getLogger(); private final String id; + @SuppressWarnings("this-escape") private final LazyReference emptyFuzzy = LazyReference.from(() -> new FuzzyBlockState(this)); //FAWE start @@ -123,7 +124,7 @@ public class BlockType implements Keyed, Pattern { * @return The id */ @Override - public String getId() { + public String id() { return this.id; } @@ -134,13 +135,13 @@ public class BlockType implements Keyed, Pattern { //FAWE start public String getNamespace() { - String id = getId(); + String id = id(); int i = id.indexOf(':'); return i == -1 ? "minecraft" : id.substring(0, i); } public String getResource() { - String id = getId(); + String id = id(); return id.substring(id.indexOf(':') + 1); } //FAWE end @@ -155,7 +156,7 @@ public class BlockType implements Keyed, Pattern { public String getName() { String name = this.name.getValue(); if (name == null || name.isEmpty()) { - return getId(); + return id(); } return name; } @@ -179,7 +180,7 @@ public class BlockType implements Keyed, Pattern { LOGGER.error( "Attempted to load blockstate with id {} of type {} outside of state ordinals length. Using default state.", propertyId, - getId() + id() ); return settings.defaultState; } @@ -188,7 +189,7 @@ public class BlockType implements Keyed, Pattern { LOGGER.error( "Attempted to load blockstate with ordinal {} of type {} outside of states length. Using default state. Using default state.", ordinal, - getId() + id() ); return settings.defaultState; } @@ -246,6 +247,17 @@ public class BlockType implements Keyed, Pattern { return this.settings.propertiesMapArr.length > ordinal && this.settings.propertiesMapArr[ordinal] != null; } + /** + * {@return whether this block type has a given property} + * + * @param property the expected property + * @since 2.12.1 + */ + public boolean hasProperty(Property property) { + int ordinal = property.getKey().getId(); + return this.settings.propertiesMapArr.length > ordinal && property.equals(this.settings.propertiesMapArr[ordinal]); + } + public Property getProperty(PropertyKey key) { try { return (Property) this.settings.propertiesMapArr[key.getId()]; @@ -404,7 +416,7 @@ public class BlockType implements Keyed, Pattern { @Override public String toString() { - return getId(); + return id(); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index 0cd3f55e5..2667d44f9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -415,6 +415,8 @@ public final class BlockTypes { @Nullable public static final BlockType CHISELED_BOOKSHELF = init(); @Nullable + public static final BlockType CHISELED_COPPER = init(); + @Nullable public static final BlockType CHISELED_DEEPSLATE = init(); @Nullable public static final BlockType CHISELED_NETHER_BRICKS = init(); @@ -429,6 +431,10 @@ public final class BlockTypes { @Nullable public static final BlockType CHISELED_STONE_BRICKS = init(); @Nullable + public static final BlockType CHISELED_TUFF = init(); + @Nullable + public static final BlockType CHISELED_TUFF_BRICKS = init(); + @Nullable public static final BlockType CHORUS_FLOWER = init(); @Nullable public static final BlockType CHORUS_PLANT = init(); @@ -471,6 +477,16 @@ public final class BlockTypes { @Nullable public static final BlockType COPPER_BLOCK = init(); @Nullable + public static final BlockType COPPER_BULB = init(); + @Nullable + public static final BlockType COPPER_DOOR = init(); + @Nullable + public static final BlockType COPPER_GRATE = init(); + @Nullable + public static final BlockType COPPER_ORE = init(); + @Nullable + public static final BlockType COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType CORNFLOWER = init(); @Nullable public static final BlockType CRACKED_DEEPSLATE_BRICKS = init(); @@ -483,6 +499,8 @@ public final class BlockTypes { @Nullable public static final BlockType CRACKED_STONE_BRICKS = init(); @Nullable + public static final BlockType CRAFTER = init(); + @Nullable public static final BlockType CRAFTING_TABLE = init(); @Nullable public static final BlockType CREEPER_HEAD = init(); @@ -751,8 +769,18 @@ public final class BlockTypes { @Nullable public static final BlockType END_STONE_BRICK_WALL = init(); @Nullable + public static final BlockType EXPOSED_CHISELED_COPPER = init(); + @Nullable public static final BlockType EXPOSED_COPPER = init(); @Nullable + public static final BlockType EXPOSED_COPPER_BULB = init(); + @Nullable + public static final BlockType EXPOSED_COPPER_DOOR = init(); + @Nullable + public static final BlockType EXPOSED_COPPER_GRATE = init(); + @Nullable + public static final BlockType EXPOSED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType EXPOSED_CUT_COPPER = init(); @Nullable public static final BlockType EXPOSED_CUT_COPPER_SLAB = init(); @@ -808,10 +836,13 @@ public final class BlockTypes { public static final BlockType GRANITE_STAIRS = init(); @Nullable public static final BlockType GRANITE_WALL = init(); - @Nullable + @Nullable @Deprecated public static final BlockType GRASS = init(); @Nullable public static final BlockType GRASS_BLOCK = init(); + @Deprecated + @Nullable + public static final BlockType GRASS_PATH = init(); @Nullable public static final BlockType GRAVEL = init(); @Nullable @@ -877,6 +908,8 @@ public final class BlockTypes { @Nullable public static final BlockType HAY_BLOCK = init(); @Nullable + public static final BlockType HEAVY_CORE = init(); + @Nullable public static final BlockType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); @Nullable public static final BlockType HONEYCOMB_BLOCK = init(); @@ -1293,8 +1326,18 @@ public final class BlockTypes { @Nullable public static final BlockType OXEYE_DAISY = init(); @Nullable + public static final BlockType OXIDIZED_CHISELED_COPPER = init(); + @Nullable public static final BlockType OXIDIZED_COPPER = init(); @Nullable + public static final BlockType OXIDIZED_COPPER_BULB = init(); + @Nullable + public static final BlockType OXIDIZED_COPPER_DOOR = init(); + @Nullable + public static final BlockType OXIDIZED_COPPER_GRATE = init(); + @Nullable + public static final BlockType OXIDIZED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType OXIDIZED_CUT_COPPER = init(); @Nullable public static final BlockType OXIDIZED_CUT_COPPER_SLAB = init(); @@ -1411,6 +1454,14 @@ public final class BlockTypes { @Nullable public static final BlockType POLISHED_GRANITE_STAIRS = init(); @Nullable + public static final BlockType POLISHED_TUFF = init(); + @Nullable + public static final BlockType POLISHED_TUFF_SLAB = init(); + @Nullable + public static final BlockType POLISHED_TUFF_STAIRS = init(); + @Nullable + public static final BlockType POLISHED_TUFF_WALL = init(); + @Nullable public static final BlockType POPPY = init(); @Nullable public static final BlockType POTATOES = init(); @@ -1667,6 +1718,8 @@ public final class BlockTypes { @Nullable public static final BlockType SEAGRASS = init(); @Nullable + public static final BlockType SHORT_GRASS = init(); + @Nullable public static final BlockType SEA_LANTERN = init(); @Nullable public static final BlockType SEA_PICKLE = init(); @@ -1874,6 +1927,8 @@ public final class BlockTypes { @Nullable public static final BlockType TRAPPED_CHEST = init(); @Nullable + public static final BlockType TRIAL_SPAWNER = init(); + @Nullable public static final BlockType TRIPWIRE = init(); @Nullable public static final BlockType TRIPWIRE_HOOK = init(); @@ -1888,14 +1943,30 @@ public final class BlockTypes { @Nullable public static final BlockType TUFF = init(); @Nullable + public static final BlockType TUFF_BRICK_SLAB = init(); + @Nullable + public static final BlockType TUFF_BRICK_STAIRS = init(); + @Nullable + public static final BlockType TUFF_BRICK_WALL = init(); + @Nullable + public static final BlockType TUFF_BRICKS = init(); + @Nullable + public static final BlockType TUFF_SLAB = init(); + @Nullable + public static final BlockType TUFF_STAIRS = init(); + @Nullable + public static final BlockType TUFF_WALL = init(); + @Nullable public static final BlockType TURTLE_EGG = init(); @Nullable public static final BlockType TWISTING_VINES = init(); @Nullable - public static final BlockType VERDANT_FROGLIGHT = init(); - @Nullable public static final BlockType TWISTING_VINES_PLANT = init(); @Nullable + public static final BlockType VAULT = init(); + @Nullable + public static final BlockType VERDANT_FROGLIGHT = init(); + @Nullable public static final BlockType VINE = init(); @Nullable public static final BlockType VOID_AIR = init(); @@ -1947,16 +2018,36 @@ public final class BlockTypes { @Nullable public static final BlockType WATER_CAULDRON = init(); @Nullable + public static final BlockType WAXED_CHISELED_COPPER = init(); + @Nullable public static final BlockType WAXED_COPPER_BLOCK = init(); @Nullable + public static final BlockType WAXED_COPPER_BULB = init(); + @Nullable + public static final BlockType WAXED_COPPER_DOOR = init(); + @Nullable + public static final BlockType WAXED_COPPER_GRATE = init(); + @Nullable + public static final BlockType WAXED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType WAXED_CUT_COPPER = init(); @Nullable public static final BlockType WAXED_CUT_COPPER_SLAB = init(); @Nullable public static final BlockType WAXED_CUT_COPPER_STAIRS = init(); @Nullable + public static final BlockType WAXED_EXPOSED_CHISELED_COPPER = init(); + @Nullable public static final BlockType WAXED_EXPOSED_COPPER = init(); @Nullable + public static final BlockType WAXED_EXPOSED_COPPER_BULB = init(); + @Nullable + public static final BlockType WAXED_EXPOSED_COPPER_DOOR = init(); + @Nullable + public static final BlockType WAXED_EXPOSED_COPPER_GRATE = init(); + @Nullable + public static final BlockType WAXED_EXPOSED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType WAXED_EXPOSED_CUT_COPPER = init(); @Nullable public static final BlockType WAXED_EXPOSED_CUT_COPPER_SLAB = init(); @@ -1965,22 +2056,52 @@ public final class BlockTypes { @Nullable public static final BlockType WAXED_OXIDIZED_COPPER = init(); @Nullable + public static final BlockType WAXED_OXIDIZED_COPPER_BULB = init(); + @Nullable + public static final BlockType WAXED_OXIDIZED_COPPER_DOOR = init(); + @Nullable + public static final BlockType WAXED_OXIDIZED_COPPER_GRATE = init(); + @Nullable + public static final BlockType WAXED_OXIDIZED_COPPER_TRAPDOOR = init(); + @Nullable + public static final BlockType WAXED_OXIDIZED_CHISELED_COPPER = init(); + @Nullable public static final BlockType WAXED_OXIDIZED_CUT_COPPER = init(); @Nullable public static final BlockType WAXED_OXIDIZED_CUT_COPPER_SLAB = init(); @Nullable public static final BlockType WAXED_OXIDIZED_CUT_COPPER_STAIRS = init(); @Nullable + public static final BlockType WAXED_WEATHERED_CHISELED_COPPER = init(); + @Nullable public static final BlockType WAXED_WEATHERED_COPPER = init(); @Nullable + public static final BlockType WAXED_WEATHERED_COPPER_BULB = init(); + @Nullable + public static final BlockType WAXED_WEATHERED_COPPER_DOOR = init(); + @Nullable + public static final BlockType WAXED_WEATHERED_COPPER_GRATE = init(); + @Nullable + public static final BlockType WAXED_WEATHERED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType WAXED_WEATHERED_CUT_COPPER = init(); @Nullable public static final BlockType WAXED_WEATHERED_CUT_COPPER_SLAB = init(); @Nullable public static final BlockType WAXED_WEATHERED_CUT_COPPER_STAIRS = init(); @Nullable + public static final BlockType WEATHERED_CHISELED_COPPER = init(); + @Nullable public static final BlockType WEATHERED_COPPER = init(); @Nullable + public static final BlockType WEATHERED_COPPER_BULB = init(); + @Nullable + public static final BlockType WEATHERED_COPPER_DOOR = init(); + @Nullable + public static final BlockType WEATHERED_COPPER_GRATE = init(); + @Nullable + public static final BlockType WEATHERED_COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType WEATHERED_CUT_COPPER = init(); @Nullable public static final BlockType WEATHERED_CUT_COPPER_SLAB = init(); @@ -2114,8 +2235,8 @@ public final class BlockTypes { throw new SuggestInputParseException(Caption.of("fawe.error.invalid-block-type", TextComponent.of(input)), () -> Stream.of( BlockTypesCache.values) - .filter(b -> StringMan.blockStateMatches(inputLower, b.getId())) - .map(BlockType::getId) + .filter(b -> StringMan.blockStateMatches(inputLower, b.id())) + .map(BlockType::id) .sorted(StringMan.blockStateComparator(inputLower)) .collect(Collectors.toList()) ); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/package-info.java index b8e54bc04..46a6490c9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/package-info.java @@ -1,6 +1,6 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.world.block.BlockTypesCache + * {@link com.sk89q.worldedit.world.block.BlockTypesCache} */ package com.sk89q.worldedit.world.block; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java index 5e4292cd4..8a3c3de89 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java @@ -19,21 +19,20 @@ package com.sk89q.worldedit.world.chunk; -import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nullable; import java.util.HashMap; @@ -41,25 +40,25 @@ import java.util.Map; public class AnvilChunk implements Chunk { - private final CompoundBinaryTag rootTag; + private final LinCompoundTag rootTag; private final byte[][] blocks; private final byte[][] blocksAdd; private final byte[][] data; private final int rootX; private final int rootZ; - private Map tileEntities; + private Map tileEntities; /** * Construct the chunk with a compound tag. * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link #AnvilChunk(CompoundBinaryTag)} + * @deprecated Use {@link #AnvilChunk(LinCompoundTag)} */ @Deprecated public AnvilChunk(CompoundTag tag) throws DataException { - this(tag.asBinaryTag()); + this(tag.toLinTag()); } /** @@ -68,45 +67,40 @@ public class AnvilChunk implements Chunk { * @param tag the tag to read * @throws DataException on a data error */ - public AnvilChunk(CompoundBinaryTag tag) throws DataException { + public AnvilChunk(LinCompoundTag tag) throws DataException { rootTag = tag; - rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); - rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); + rootX = rootTag.getTag("xPos", LinTagType.intTag()).value(); + rootZ = rootTag.getTag("zPos", LinTagType.intTag()).value(); blocks = new byte[16][16 * 16 * 16]; blocksAdd = new byte[16][16 * 16 * 8]; data = new byte[16][16 * 16 * 8]; - ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); + LinListTag> sections = rootTag.getTag("Sections", LinTagType.listTag()); - for (BinaryTag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundBinaryTag)) { + for (LinTag rawSectionTag : sections.value()) { + if (!(rawSectionTag instanceof LinCompoundTag sectionTag)) { continue; } - CompoundBinaryTag sectionTag = (CompoundBinaryTag) rawSectionTag; - if (sectionTag.get("Y") == null) { + var sectionYTag = sectionTag.findTag("Y", LinTagType.byteTag()); + if (sectionYTag == null) { continue; // Empty section. } - int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); + int y = sectionYTag.value(); if (y < 0 || y >= 16) { continue; } - blocks[y] = NbtUtils.getChildTag(sectionTag, - "Blocks", BinaryTagTypes.BYTE_ARRAY - ).value(); - data[y] = NbtUtils.getChildTag(sectionTag, "Data", - BinaryTagTypes.BYTE_ARRAY - ).value(); + blocks[y] = sectionTag.getTag("Blocks", LinTagType.byteArrayTag()).value(); + data[y] = sectionTag.getTag("Data", LinTagType.byteArrayTag()).value(); // 4096 ID block support - if (sectionTag.get("Add") != null) { - blocksAdd[y] = NbtUtils.getChildTag(sectionTag, - "Add", BinaryTagTypes.BYTE_ARRAY - ).value(); + var addTag = sectionTag.findTag("Add", LinTagType.byteArrayTag()); + if (addTag != null) { + blocksAdd[y] = addTag.value(); } } @@ -130,9 +124,9 @@ public class AnvilChunk implements Chunk { } private int getBlockID(BlockVector3 position) throws DataException { - int x = position.getX() - rootX * 16; - int y = position.getY(); - int z = position.getZ() - rootZ * 16; + int x = position.x() - rootX * 16; + int y = position.y(); + int z = position.z() - rootZ * 16; int section = y >> 4; if (section < 0 || section >= blocks.length) { @@ -144,17 +138,12 @@ public class AnvilChunk implements Chunk { int index = x + (z * 16 + (yindex * 16 * 16)); try { - int addId = 0; - // The block ID is the combination of the Blocks byte array with the // Add byte array. 'Blocks' stores the lowest 8 bits of a block's ID, and // 'Add' stores the highest 4 bits of the ID. The first block is stored // in the lowest nibble in the Add byte array. - if (index % 2 == 0) { - addId = (blocksAdd[section][index >> 1] & 0x0F) << 8; - } else { - addId = (blocksAdd[section][index >> 1] & 0xF0) << 4; - } + byte addByte = blocksAdd[section][index >> 1]; + int addId = (index & 1) == 0 ? (addByte & 0x0F) << 8 : (addByte & 0xF0) << 4; return (blocks[section][index] & 0xFF) + addId; } catch (IndexOutOfBoundsException e) { @@ -163,9 +152,9 @@ public class AnvilChunk implements Chunk { } private int getBlockData(BlockVector3 position) throws DataException { - int x = position.getX() - rootX * 16; - int y = position.getY(); - int z = position.getZ() - rootZ * 16; + int x = position.x() - rootX * 16; + int y = position.y(); + int z = position.z() - rootZ * 16; int section = y >> 4; int yIndex = y & 0x0F; @@ -175,15 +164,12 @@ public class AnvilChunk implements Chunk { } int index = x + (z * 16 + (yIndex * 16 * 16)); - boolean shift = index % 2 == 0; - index /= 2; + boolean shift = (index & 1) != 0; + index >>= 2; try { - if (!shift) { - return (data[section][index] & 0xF0) >> 4; - } else { - return data[section][index] & 0xF; - } + byte dataByte = data[section][index]; + return shift ? (dataByte & 0xF0) >> 4 : dataByte & 0x0F; } catch (IndexOutOfBoundsException e) { throw new DataException("Chunk does not contain position " + position); } @@ -192,44 +178,40 @@ public class AnvilChunk implements Chunk { /** * Used to load the tile entities. */ - private void populateTileEntities() throws DataException { - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); + private void populateTileEntities() { + LinListTag tags = rootTag.getTag("TileEntities", LinTagType.listTag()) + .asTypeChecked(LinTagType.compoundTag()); - tileEntities = new HashMap<>(); - - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in TileEntities"); - } - - CompoundBinaryTag t = (CompoundBinaryTag) tag; + tileEntities = new HashMap<>(tags.value().size()); + for (LinCompoundTag t : tags.value()) { int x = 0; int y = 0; int z = 0; - CompoundBinaryTag.Builder values = CompoundBinaryTag.builder(); + LinCompoundTag.Builder values = LinCompoundTag.builder(); - for (String key : t.keySet()) { - BinaryTag value = t.get(key); + for (String key : t.value().keySet()) { + LinTag value = t.value().get(key); switch (key) { - case "x": - if (value instanceof IntBinaryTag) { - x = ((IntBinaryTag) value).value(); + case "x" -> { + if (value instanceof LinIntTag v) { + x = v.valueAsInt(); } - break; - case "y": - if (value instanceof IntBinaryTag) { - y = ((IntBinaryTag) value).value(); + } + case "y" -> { + if (value instanceof LinIntTag v) { + y = v.valueAsInt(); } - break; - case "z": - if (value instanceof IntBinaryTag) { - z = ((IntBinaryTag) value).value(); + } + case "z" -> { + if (value instanceof LinIntTag v) { + z = v.valueAsInt(); } - break; - default: - break; + } + default -> { + // Do nothing. + } } values.put(key, value); @@ -250,14 +232,12 @@ public class AnvilChunk implements Chunk { * @throws DataException thrown if there is a data error */ @Nullable - private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { + private LinCompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - CompoundBinaryTag values = tileEntities.get(position); - - return values; + return tileEntities.get(position); } @Override @@ -270,7 +250,7 @@ public class AnvilChunk implements Chunk { WorldEdit.logger.warn("Unknown legacy block " + id + ":" + data + " found when loading legacy anvil chunk."); return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - CompoundBinaryTag tileEntity = getBlockTileEntity(position); + LinCompoundTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java index e1cb08bc8..9b3d54027 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java @@ -19,17 +19,12 @@ package com.sk89q.worldedit.world.chunk; -import com.fastasyncworldedit.core.util.NbtUtils; +import com.google.common.collect.ImmutableMap; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -39,10 +34,14 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nullable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,26 +50,28 @@ import java.util.Map; */ public class AnvilChunk13 implements Chunk { - protected final CompoundBinaryTag rootTag; + protected final LinCompoundTag rootTag; + private final BlockState[][] blocks; //FAWE start - biome and entity restore protected BiomeType[] biomes; - //FAWE end - private Map tileEntities; - //FAWE start - biome and entity restore private List entities; //FAWE end + private Map tileEntities; + private final int rootX; + private final int rootZ; + /** * Construct the chunk with a compound tag. * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link #AnvilChunk13(CompoundBinaryTag)} + * @deprecated Use {@link #AnvilChunk13(LinCompoundTag)} */ @Deprecated public AnvilChunk13(CompoundTag tag) throws DataException { - this(tag.asBinaryTag()); + this(tag.toLinTag()); } /** @@ -79,53 +80,58 @@ public class AnvilChunk13 implements Chunk { * @param tag the tag to read * @throws DataException on a data error */ - public AnvilChunk13(CompoundBinaryTag tag) throws DataException { + public AnvilChunk13(LinCompoundTag tag) throws DataException { rootTag = tag; + rootX = rootTag.getTag("xPos", LinTagType.intTag()).valueAsInt(); + rootZ = rootTag.getTag("zPos", LinTagType.intTag()).valueAsInt(); + blocks = new BlockState[16][]; - ListBinaryTag sections = NbtUtils.getChildTag(rootTag, "Sections", BinaryTagTypes.LIST); + LinListTag> sections = rootTag.getTag("Sections", LinTagType.listTag()); - for (BinaryTag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundBinaryTag)) { + for (LinTag rawSectionTag : sections.value()) { + if (!(rawSectionTag instanceof LinCompoundTag sectionTag)) { continue; } - CompoundBinaryTag sectionTag = (CompoundBinaryTag) rawSectionTag; - if (sectionTag.get("Y") == null) { + var sectionYTag = sectionTag.findTag("Y", LinTagType.byteTag()); + if (sectionYTag == null) { continue; // Empty section. } - int y = NbtUtils.getChildTag(sectionTag, "Y", BinaryTagTypes.BYTE).value(); + int y = sectionYTag.value(); if (y < 0 || y >= 16) { continue; } // parse palette - ListBinaryTag paletteEntries = sectionTag.getList("Palette", BinaryTagTypes.COMPOUND); - int paletteSize = paletteEntries.size(); + LinListTag paletteEntries = sectionTag.getTag( + "Palette", LinTagType.listTag() + ).asTypeChecked(LinTagType.compoundTag()); + int paletteSize = paletteEntries.value().size(); if (paletteSize == 0) { continue; } BlockState[] palette = new BlockState[paletteSize]; for (int paletteEntryId = 0; paletteEntryId < paletteSize; paletteEntryId++) { - CompoundBinaryTag paletteEntry = (CompoundBinaryTag) paletteEntries.get(paletteEntryId); - BlockType type = BlockTypes.get(paletteEntry.getString("Name")); + LinCompoundTag paletteEntry = paletteEntries.get(paletteEntryId); + String blockType = paletteEntry.getTag("Name", LinTagType.stringTag()).value(); + BlockType type = BlockTypes.get(blockType); if (type == null) { - throw new InvalidFormatException("Invalid block type: " + paletteEntry.getString("Name")); + throw new InvalidFormatException("Invalid block type: " + blockType); } BlockState blockState = type.getDefaultState(); - if (paletteEntry.get("Properties") != null) { - CompoundBinaryTag properties = NbtUtils.getChildTag(paletteEntry, "Properties", BinaryTagTypes.COMPOUND); + var propertiesTag = paletteEntry.findTag("Properties", LinTagType.compoundTag()); + if (propertiesTag != null) { for (Property property : blockState.getStates().keySet()) { - if (properties.get(property.getName()) != null) { - String value = properties.getString(property.getName()); + var propertyName = propertiesTag.findTag(property.getName(), LinTagType.stringTag()); + if (propertyName != null) { + String value = propertyName.value(); try { blockState = getBlockStateWith(blockState, property, value); } catch (IllegalArgumentException e) { - throw new InvalidFormatException("Invalid block state for " + blockState - .getBlockType() - .getId() + ", " + property.getName() + ": " + value); + throw new InvalidFormatException("Invalid block state for " + blockState.getBlockType().id() + ", " + property.getName() + ": " + value); } } } @@ -134,7 +140,7 @@ public class AnvilChunk13 implements Chunk { } // parse block states - long[] blockStatesSerialized = NbtUtils.getChildTag(sectionTag, "BlockStates", BinaryTagTypes.LONG_ARRAY).value(); + long[] blockStatesSerialized = sectionTag.getTag("BlockStates", LinTagType.longArrayTag()).value(); BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; blocks[y] = chunkSectionBlocks; @@ -143,8 +149,7 @@ public class AnvilChunk13 implements Chunk { } } - protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws - InvalidFormatException { + protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws InvalidFormatException { int paletteBits = 4; while ((1 << paletteBits) < palette.length) { ++paletteBits; @@ -163,7 +168,7 @@ public class AnvilChunk13 implements Chunk { throw new InvalidFormatException("Too short block state table"); } currentSerializedValue = blockStatesSerialized[nextSerializedItem++]; - localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits; + localBlockId |= (int) (currentSerializedValue & ((1L << bitsNextLong) - 1)) << remainingBits; currentSerializedValue >>>= bitsNextLong; remainingBits = 64 - bitsNextLong; } else { @@ -185,27 +190,23 @@ public class AnvilChunk13 implements Chunk { /** * Used to load the tile entities. */ - private void populateTileEntities() throws DataException { - tileEntities = new HashMap<>(); - if (rootTag.get("TileEntities") == null) { - return; + private Map populateTileEntities() { + LinListTag tags = rootTag.findListTag( + "TileEntities", LinTagType.compoundTag() + ); + if (tags == null) { + return ImmutableMap.of(); } - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); - - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in TileEntities"); - } - - CompoundBinaryTag t = (CompoundBinaryTag) tag; - - int x = ((IntBinaryTag) t.get("x")).value(); - int y = ((IntBinaryTag) t.get("y")).value(); - int z = ((IntBinaryTag) t.get("z")).value(); + var tileEntities = ImmutableMap.builderWithExpectedSize(tags.value().size()); + for (LinCompoundTag tag : tags.value()) { + int x = tag.getTag("x", LinTagType.intTag()).valueAsInt(); + int y = tag.getTag("y", LinTagType.intTag()).valueAsInt(); + int z = tag.getTag("z", LinTagType.intTag()).valueAsInt(); BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, t); + tileEntities.put(vec, tag); } + return tileEntities.build(); } /** @@ -215,26 +216,21 @@ public class AnvilChunk13 implements Chunk { * * @param position the position * @return the compound tag for that position, which may be null - * @throws DataException thrown if there is a data error */ @Nullable - private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { + private LinCompoundTag getBlockTileEntity(BlockVector3 position) { if (tileEntities == null) { - populateTileEntities(); + this.tileEntities = populateTileEntities(); } - CompoundBinaryTag values = tileEntities.get(position); - - return values; + return tileEntities.get(position); } @Override public BaseBlock getBlock(BlockVector3 position) throws DataException { - //FAWE start - simplified - int x = position.getX() & 15; - int y = position.getY(); - int z = position.getZ() & 15; - //FAWE end + int x = position.x() - rootX * 16; + int y = position.y(); + int z = position.z() - rootZ * 16; int section = y >> 4; int yIndex = y & 0x0F; @@ -246,23 +242,18 @@ public class AnvilChunk13 implements Chunk { BlockState[] sectionBlocks = blocks[section]; BlockState state = sectionBlocks != null ? sectionBlocks[(yIndex << 8) | (z << 4) | x] : BlockTypes.AIR.getDefaultState(); - CompoundBinaryTag tileEntity = getBlockTileEntity(position); + LinCompoundTag tileEntity = getBlockTileEntity(position); - if (tileEntity != null) { - return state.toBaseBlock(tileEntity); - } - - return state.toBaseBlock(); - } - //FAWE start - biome and entity restore + return state.toBaseBlock(tileEntity); + } //FAWE start - biome and entity restore @Override public BiomeType getBiome(final BlockVector3 position) throws DataException { if (biomes == null) { populateBiomes(); } - int rx = position.getX() & 15; - int rz = position.getZ() & 15; + int rx = position.x() & 15; + int rz = position.z() & 15; return biomes[rz << 4 | rx]; } @@ -277,21 +268,20 @@ public class AnvilChunk13 implements Chunk { /** * Used to load the biomes. */ - private void populateEntities() throws DataException { + private void populateEntities() { entities = new ArrayList<>(); - if (rootTag.get("Entities") == null) { + LinListTag tags = rootTag.findListTag( + "Entities", LinTagType.compoundTag() + ); + if (tags == null) { return; } - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "Entities", BinaryTagTypes.LIST); - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in Entities"); - } - - CompoundBinaryTag t = (CompoundBinaryTag) tag; - - entities.add(new BaseEntity(EntityTypes.get(t.getString("id")), LazyReference.computed(t))); + for (LinCompoundTag tag : tags.value()) { + entities.add(new BaseEntity( + EntityTypes.get(tag.getTag("id", LinTagType.stringTag()).value()), + LazyReference.computed(tag) + )); } } @@ -299,12 +289,13 @@ public class AnvilChunk13 implements Chunk { /** * Used to load the biomes. */ - private void populateBiomes() throws DataException { + private void populateBiomes() { biomes = new BiomeType[256]; - if (rootTag.get("Biomes") == null) { + LinIntArrayTag biomeTag = rootTag.findTag("Biomes", LinTagType.intArrayTag()); + if (biomeTag == null) { return; } - int[] stored = NbtUtils.getChildTag(rootTag, "Biomes", BinaryTagTypes.INT_ARRAY).value(); + int[] stored = biomeTag.value(); for (int i = 0; i < 256; i++) { biomes[i] = BiomeTypes.getLegacy(stored[i]); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk15.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk15.java index 7565f66c1..955a6e70a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk15.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk15.java @@ -19,14 +19,14 @@ package com.sk89q.worldedit.world.chunk; -import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinTagType; /** * The chunk format for Minecraft 1.15 and newer @@ -38,7 +38,7 @@ public class AnvilChunk15 extends AnvilChunk13 { * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link #AnvilChunk15(CompoundBinaryTag)} + * @deprecated Use {@link #AnvilChunk15(LinCompoundTag)} */ @Deprecated public AnvilChunk15(CompoundTag tag) throws DataException { @@ -51,7 +51,7 @@ public class AnvilChunk15 extends AnvilChunk13 { * @param tag the tag to read * @throws DataException on a data error */ - public AnvilChunk15(CompoundBinaryTag tag) throws DataException { + public AnvilChunk15(LinCompoundTag tag) throws DataException { super(tag); } @@ -60,18 +60,19 @@ public class AnvilChunk15 extends AnvilChunk13 { if (biomes == null) { populateBiomes(); } - int x = (position.getX() & 15) >> 2; - int y = position.getY() >> 2; - int z = (position.getZ() & 15) >> 2; + int x = (position.x() & 15) >> 2; + int y = position.y() >> 2; + int z = (position.z() & 15) >> 2; return biomes[y << 4 | z << 2 | x]; } private void populateBiomes() throws DataException { biomes = new BiomeType[1024]; - if (rootTag.get("Biomes") == null) { + LinIntArrayTag biomeTag = rootTag.findTag("Biomes", LinTagType.intArrayTag()); + if (biomeTag == null) { return; } - int[] stored = NbtUtils.getChildTag(rootTag, "Biomes", BinaryTagTypes.INT_ARRAY).value(); + int[] stored = biomeTag.value(); for (int i = 0; i < 1024; i++) { biomes[i] = BiomeTypes.getLegacy(stored[i]); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java index 92f7f6caf..ff4c89e65 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk16.java @@ -20,10 +20,10 @@ package com.sk89q.worldedit.world.chunk; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinCompoundTag; /** * The chunk format for Minecraft 1.16 and 1.17 @@ -35,7 +35,7 @@ public class AnvilChunk16 extends AnvilChunk15 { * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link #AnvilChunk16(CompoundBinaryTag)} + * @deprecated Use {@link #AnvilChunk16(LinCompoundTag)} */ @Deprecated public AnvilChunk16(CompoundTag tag) throws DataException { @@ -48,7 +48,7 @@ public class AnvilChunk16 extends AnvilChunk15 { * @param tag the tag to read * @throws DataException on a data error */ - public AnvilChunk16(CompoundBinaryTag tag) throws DataException { + public AnvilChunk16(LinCompoundTag tag) throws DataException { super(tag); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk17.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk17.java index a6fa95b53..fbddb66f0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk17.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk17.java @@ -20,16 +20,12 @@ package com.sk89q.worldedit.world.chunk; import com.fastasyncworldedit.core.util.NbtUtils; +import com.google.common.collect.ImmutableMap; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -39,10 +35,15 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nullable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Supplier; @@ -52,11 +53,11 @@ import java.util.function.Supplier; */ public class AnvilChunk17 implements Chunk { - private final CompoundBinaryTag rootTag; - private final Supplier entityTagSupplier; + private final LinCompoundTag rootTag; + private final Supplier entityTagSupplier; private BiomeType[] biomes; private BlockState[][] blocks; - private Map tileEntities; + private Map tileEntities; private List entities; // initialise with default values private int minSectionPosition = 0; @@ -68,16 +69,16 @@ public class AnvilChunk17 implements Chunk { * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link #AnvilChunk17(CompoundBinaryTag, Supplier)} + * @deprecated Use {@link #AnvilChunk17(LinCompoundTag, Supplier)} */ @Deprecated public AnvilChunk17(CompoundTag tag, Supplier entitiesTag) throws DataException { - this(tag.asBinaryTag(), () -> { + this(tag.toLinTag(), () -> { CompoundTag compoundTag = entitiesTag.get(); if (compoundTag == null) { return null; } - return compoundTag.asBinaryTag(); + return compoundTag.toLinTag(); }); } @@ -89,20 +90,21 @@ public class AnvilChunk17 implements Chunk { * {@link #getEntities()} is called * @throws DataException on a data error */ - public AnvilChunk17(CompoundBinaryTag tag, Supplier entityTag) throws DataException { + public AnvilChunk17(LinCompoundTag tag, Supplier entityTag) throws DataException { rootTag = tag; entityTagSupplier = entityTag; blocks = new BlockState[16][]; // initialise with default length - ListBinaryTag sections = rootTag.getList("Sections"); + LinListTag> sections = rootTag.getTag("Sections", LinTagType.listTag()); - for (BinaryTag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundBinaryTag sectionTag)) { + for (LinTag rawSectionTag : sections.value()) { + if (!(rawSectionTag instanceof LinCompoundTag sectionTag)) { continue; } - if (sectionTag.get("Y") == null || sectionTag.get("BlockStates") == null) { + var sectionYTag = sectionTag.findTag("Y", LinTagType.byteTag()); + if (sectionYTag == null) { continue; // Empty section. } @@ -110,30 +112,32 @@ public class AnvilChunk17 implements Chunk { updateSectionIndexRange(y); // parse palette - ListBinaryTag paletteEntries = sectionTag.getList("Palette", BinaryTagTypes.COMPOUND); - int paletteSize = paletteEntries.size(); + LinListTag paletteEntries = sectionTag.getListTag("Palette", LinTagType.compoundTag()); + int paletteSize = paletteEntries.value().size(); if (paletteSize == 0) { continue; } BlockState[] palette = new BlockState[paletteSize]; for (int paletteEntryId = 0; paletteEntryId < paletteSize; paletteEntryId++) { - CompoundBinaryTag paletteEntry = (CompoundBinaryTag) paletteEntries.get(paletteEntryId); - BlockType type = BlockTypes.get(paletteEntry.getString("Name")); + LinCompoundTag paletteEntry = (LinCompoundTag) paletteEntries.get(paletteEntryId); + BlockType type = BlockTypes.get(paletteEntry.getTag("Name", LinTagType.stringTag()).value()); if (type == null) { - throw new InvalidFormatException("Invalid block type: " + paletteEntry.getString("Name")); + throw new InvalidFormatException("Invalid block type: " + paletteEntry + .getTag("Name", LinTagType.stringTag()) + .value()); } BlockState blockState = type.getDefaultState(); - if (paletteEntry.get("Properties") != null) { - CompoundBinaryTag properties = NbtUtils.getChildTag(paletteEntry, "Properties", BinaryTagTypes.COMPOUND); + LinCompoundTag properties = paletteEntry.findTag("Properties", LinTagType.compoundTag()); + if (properties != null) { for (Property property : blockState.getStates().keySet()) { - if (properties.get(property.getName()) != null) { - String value = properties.getString(property.getName()); + LinStringTag stringTag = properties.findTag(property.getName(), LinTagType.stringTag()); + if (stringTag != null) { try { - blockState = getBlockStateWith(blockState, property, value); + blockState = getBlockStateWith(blockState, property, stringTag.value()); } catch (IllegalArgumentException e) { throw new InvalidFormatException("Invalid block state for " + blockState .getBlockType() - .getId() + ", " + property.getName() + ": " + value); + .id() + ", " + property.getName() + ": " + stringTag.value()); } } } @@ -142,7 +146,7 @@ public class AnvilChunk17 implements Chunk { } // parse block states - long[] blockStatesSerialized = sectionTag.getLongArray("BlockStates"); + long[] blockStatesSerialized = sectionTag.getTag("BlockStates", LinTagType.longArrayTag()).value(); BlockState[] chunkSectionBlocks = new BlockState[4096]; blocks[y - minSectionPosition] = chunkSectionBlocks; @@ -191,27 +195,24 @@ public class AnvilChunk17 implements Chunk { /** * Used to load the tile entities. */ - private void populateTileEntities() throws DataException { - tileEntities = new HashMap<>(); - if (rootTag.get("TileEntities") == null) { + private void populateTileEntities() { + LinListTag tags = rootTag.findListTag( + "TileEntities", LinTagType.compoundTag() + ); + if (tags == null) { + tileEntities = ImmutableMap.of(); return; } - ListBinaryTag tags = rootTag.getList("TileEntities"); - - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in TileEntities"); - } - - CompoundBinaryTag t = (CompoundBinaryTag) tag; - - int x = ((IntBinaryTag) t.get("x")).value(); - int y = ((IntBinaryTag) t.get("y")).value(); - int z = ((IntBinaryTag) t.get("z")).value(); + var tileEntitiesBuilder = ImmutableMap.builderWithExpectedSize(tags.value().size()); + for (LinCompoundTag tag : tags.value()) { + int x = tag.getTag("x", LinTagType.intTag()).valueAsInt(); + int y = tag.getTag("y", LinTagType.intTag()).valueAsInt(); + int z = tag.getTag("z", LinTagType.intTag()).valueAsInt(); BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, t); + tileEntities.put(vec, tag); } + tileEntities = tileEntitiesBuilder.build(); } /** @@ -224,7 +225,7 @@ public class AnvilChunk17 implements Chunk { * @throws DataException thrown if there is a data error */ @Nullable - private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { + private LinCompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } @@ -234,9 +235,9 @@ public class AnvilChunk17 implements Chunk { @Override public BaseBlock getBlock(BlockVector3 position) throws DataException { - int x = position.getX() & 15; - int y = position.getY(); - int z = position.getZ() & 15; + int x = position.x() & 15; + int y = position.y(); + int z = position.z() & 15; int section = y >> 4; int yIndex = y & 0x0F; @@ -248,7 +249,7 @@ public class AnvilChunk17 implements Chunk { BlockState[] sectionBlocks = blocks[section - minSectionPosition]; BlockState state = sectionBlocks != null ? sectionBlocks[(yIndex << 8) | (z << 4) | x] : BlockTypes.AIR.getDefaultState(); - CompoundBinaryTag tileEntity = getBlockTileEntity(position); + LinCompoundTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); @@ -262,18 +263,19 @@ public class AnvilChunk17 implements Chunk { if (biomes == null) { populateBiomes(); } - int x = (position.getX() & 15) >> 2; - int y = (position.getY() - (minSectionPosition << 4)) >> 2; // normalize - int z = (position.getZ() & 15) >> 2; + int x = (position.x() & 15) >> 2; + int y = (position.y() - (minSectionPosition << 4)) >> 2; // normalize + int z = (position.z() & 15) >> 2; return biomes[y << 4 | z << 2 | x]; } private void populateBiomes() throws DataException { biomes = new BiomeType[64 * blocks.length]; - if (rootTag.get("Biomes") == null) { + LinIntArrayTag biomeTag = rootTag.findTag("Biomes", LinTagType.intArrayTag()); + if (biomeTag == null) { return; } - int[] stored = rootTag.getIntArray("Biomes"); + int[] stored = biomeTag.value(); for (int i = 0; i < 1024; i++) { biomes[i] = BiomeTypes.getLegacy(stored[i]); } @@ -290,22 +292,21 @@ public class AnvilChunk17 implements Chunk { /** * Used to load the biomes. */ - private void populateEntities() throws DataException { + private void populateEntities() { entities = new ArrayList<>(); - CompoundBinaryTag entityTag; - if (entityTagSupplier == null || (entityTag = entityTagSupplier.get()) == null) { + LinListTag tags = rootTag.findListTag( + "Entities", LinTagType.compoundTag() + ); + if (tags == null) { return; } - ListBinaryTag tags = entityTag.getList("Entities"); - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in Entities"); - } + for (LinCompoundTag tag : tags.value()) { - CompoundBinaryTag t = (CompoundBinaryTag) tag; - - entities.add(new BaseEntity(EntityTypes.get(t.getString("id")), LazyReference.computed(t))); + entities.add(new BaseEntity( + EntityTypes.get(tag.getTag("id", LinTagType.stringTag()).value()), + LazyReference.computed(tag) + )); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java index bb18e8ed5..c5736bfd5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java @@ -19,134 +19,93 @@ package com.sk89q.worldedit.world.chunk; -import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.LongArrayTag; +import com.sk89q.jnbt.NBTUtils; +import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.storage.InvalidFormatException; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import javax.annotation.Nullable; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Supplier; /** * The chunk format for Minecraft 1.18 and newer */ public class AnvilChunk18 implements Chunk { - //FAWE start - CBT - private final CompoundBinaryTag rootTag; - //FAWE end + private final CompoundTag rootTag; private final Int2ObjectOpenHashMap blocks; - //FAWE start - entity and biome restore - private final int sectionCount; - private final Supplier entityTagSupplier; - private Int2ObjectOpenHashMap biomes = null; - private List entities; - private Map tileEntities; - //FAWE end + private final int rootX; + private final int rootZ; + private Map>> tileEntities; /** * Construct the chunk with a compound tag. * * @param tag the tag to read * @throws DataException on a data error - * @deprecated Use {@link AnvilChunk18#AnvilChunk18(CompoundBinaryTag, Supplier)} */ - @Deprecated public AnvilChunk18(CompoundTag tag) throws DataException { - //FAWE start - CBT - this(tag.asBinaryTag(), () -> null); - } - - /** - * Construct the chunk with a compound tag. - * - * @param tag the tag to read - * @throws DataException on a data error - * @deprecated Use {@link AnvilChunk18#AnvilChunk18(CompoundBinaryTag, Supplier)} - * @since 2.1.0 - */ - @Deprecated - public AnvilChunk18(CompoundTag tag, Supplier entitiesTag) throws DataException { - //FAWE start - CBT - this(tag.asBinaryTag(), () -> { - CompoundTag compoundTag = entitiesTag.get(); - return compoundTag == null ? null : compoundTag.asBinaryTag(); - }); - } - - /** - * Construct the chunk with a compound tag. - * - * @param tag the tag to read - * @throws DataException on a data error - * @since 2.1.0 - */ - public AnvilChunk18(CompoundBinaryTag tag, Supplier entityTag) throws DataException { - //FAWE end rootTag = tag; - entityTagSupplier = entityTag; - //FAWE start - CBT - ListBinaryTag sections = rootTag.getList("sections"); - this.sectionCount = sections.size(); + rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue(); + rootZ = NBTUtils.getChildTag(rootTag.getValue(), "zPos", IntTag.class).getValue(); + List sections = NBTUtils.getChildTag(rootTag.getValue(), "sections", ListTag.class).getValue(); blocks = new Int2ObjectOpenHashMap<>(sections.size()); - for (BinaryTag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundBinaryTag sectionTag)) { + for (Tag rawSectionTag : sections) { + if (!(rawSectionTag instanceof CompoundTag)) { continue; } - int y = NbtUtils.getInt(sectionTag, "Y"); // sometimes a byte, sometimes an int + CompoundTag sectionTag = (CompoundTag) rawSectionTag; + Object yValue = sectionTag.getValue().get("Y").getValue(); // sometimes a byte, sometimes an int + if (!(yValue instanceof Number)) { + throw new InvalidFormatException("Y is not numeric: " + yValue); + } + int y = ((Number) yValue).intValue(); - BinaryTag rawBlockStatesTag = sectionTag.get("block_states"); // null for sections outside of the world limits - if (rawBlockStatesTag instanceof CompoundBinaryTag blockStatesTag) { + Tag rawBlockStatesTag = sectionTag.getValue().get("block_states"); // null for sections outside of the world limits + if (rawBlockStatesTag instanceof CompoundTag) { + CompoundTag blockStatesTag = (CompoundTag) rawBlockStatesTag; // parse palette - ListBinaryTag paletteEntries = blockStatesTag.getList("palette"); + List paletteEntries = blockStatesTag.getList("palette", CompoundTag.class); int paletteSize = paletteEntries.size(); if (paletteSize == 0) { continue; } BlockState[] palette = new BlockState[paletteSize]; for (int paletteEntryId = 0; paletteEntryId < paletteSize; paletteEntryId++) { - CompoundBinaryTag paletteEntry = (CompoundBinaryTag) paletteEntries.get(paletteEntryId); + CompoundTag paletteEntry = paletteEntries.get(paletteEntryId); BlockType type = BlockTypes.get(paletteEntry.getString("Name")); if (type == null) { throw new InvalidFormatException("Invalid block type: " + paletteEntry.getString("Name")); } BlockState blockState = type.getDefaultState(); - BinaryTag propertiesTag = paletteEntry.get("Properties"); - if (propertiesTag instanceof CompoundBinaryTag properties) { + if (paletteEntry.containsKey("Properties")) { + CompoundTag properties = NBTUtils.getChildTag(paletteEntry.getValue(), "Properties", CompoundTag.class); for (Property property : blockState.getStates().keySet()) { - String value; - if (!(value = properties.getString(property.getName())).isEmpty()) { + if (properties.containsKey(property.getName())) { + String value = properties.getString(property.getName()); try { blockState = getBlockStateWith(blockState, property, value); } catch (IllegalArgumentException e) { - throw new InvalidFormatException("Invalid block state for " + blockState - .getBlockType() - .getId() + ", " + property.getName() + ": " + value); + throw new InvalidFormatException("Invalid block state for " + blockState.getBlockType().getId() + ", " + property.getName() + ": " + value); } } } @@ -160,7 +119,7 @@ public class AnvilChunk18 implements Chunk { } // parse block states - long[] blockStatesSerialized = blockStatesTag.getLongArray("data"); + long[] blockStatesSerialized = NBTUtils.getChildTag(blockStatesTag.getValue(), "data", LongArrayTag.class).getValue(); BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; blocks.put(y, chunkSectionBlocks); @@ -168,7 +127,6 @@ public class AnvilChunk18 implements Chunk { readBlockStates(palette, blockStatesSerialized, chunkSectionBlocks); } } - //FAWE end } protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws InvalidFormatException { @@ -190,24 +148,28 @@ public class AnvilChunk18 implements Chunk { * Used to load the tile entities. */ private void populateTileEntities() throws DataException { - //FAWE start - CBT tileEntities = new HashMap<>(); - if (!(rootTag.get("block_entities") instanceof ListBinaryTag tags)) { + if (!rootTag.getValue().containsKey("block_entities")) { return; } - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag t)) { + List tags = NBTUtils.getChildTag(rootTag.getValue(), + "block_entities", ListTag.class).getValue(); + + for (Tag tag : tags) { + if (!(tag instanceof CompoundTag)) { throw new InvalidFormatException("CompoundTag expected in block_entities"); } - int x = t.getInt("x"); - int y = t.getInt("y"); - int z = t.getInt("z"); + CompoundTag t = (CompoundTag) tag; + + Map> values = new HashMap<>(t.getValue()); + int x = ((IntTag) values.get("x")).getValue(); + int y = ((IntTag) values.get("y")).getValue(); + int z = ((IntTag) values.get("z")).getValue(); BlockVector3 vec = BlockVector3.at(x, y, z); - tileEntities.put(vec, t); + tileEntities.put(vec, values); } - //FAWE end } /** @@ -220,21 +182,24 @@ public class AnvilChunk18 implements Chunk { * @throws DataException thrown if there is a data error */ @Nullable - private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { - //FAWE start - CBT + private CompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - return tileEntities.get(position); - //FAWE end + Map> values = tileEntities.get(position); + if (values == null) { + return null; + } + + return new CompoundTag(values); } @Override public BaseBlock getBlock(BlockVector3 position) throws DataException { - int x = position.getX() & 15; + int x = position.getX() - rootX * 16; int y = position.getY(); - int z = position.getZ() & 15; + int z = position.getZ() - rootZ * 16; int section = y >> 4; int yIndex = y & 0x0F; @@ -245,7 +210,7 @@ public class AnvilChunk18 implements Chunk { } BlockState state = sectionBlocks[sectionBlocks.length == 1 ? 0 : ((yIndex << 8) | (z << 4) | x)]; - CompoundBinaryTag tileEntity = getBlockTileEntity(position); + CompoundTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); @@ -254,110 +219,4 @@ public class AnvilChunk18 implements Chunk { return state.toBaseBlock(); } - @Override - public BiomeType getBiome(final BlockVector3 position) throws DataException { - if (biomes == null) { - populateBiomes(); - } - int x = (position.getX() & 15) >> 2; - int y = (position.getY() & 15) >> 2; - int z = (position.getZ() & 15) >> 2; - int section = position.getY() >> 4; - BiomeType[] sectionBiomes = biomes.get(section); - if (sectionBiomes.length == 1) { - return sectionBiomes[0]; - } - return biomes.get(section)[y << 4 | z << 2 | x]; - } - - private void populateBiomes() throws DataException { - biomes = new Int2ObjectOpenHashMap<>(sectionCount); - ListBinaryTag sections = rootTag.getList("sections"); - for (BinaryTag rawSectionTag : sections) { - if (!(rawSectionTag instanceof CompoundBinaryTag sectionTag)) { - continue; - } - - int y = NbtUtils.getInt(sectionTag, "Y"); // sometimes a byte, sometimes an int - - BinaryTag rawBlockStatesTag = sectionTag.get("biomes"); // null for sections outside of the world limits - if (rawBlockStatesTag instanceof CompoundBinaryTag biomeTypesTag) { - - // parse palette - ListBinaryTag paletteEntries = biomeTypesTag.getList("palette"); - int paletteSize = paletteEntries.size(); - if (paletteSize == 0) { - continue; - } - BiomeType[] palette = new BiomeType[paletteSize]; - for (int paletteEntryId = 0; paletteEntryId < paletteSize; paletteEntryId++) { - String paletteEntry = paletteEntries.getString(paletteEntryId); - BiomeType type = BiomeType.REGISTRY.get(paletteEntry); - if (type == null) { - throw new InvalidFormatException("Invalid biome type: " + paletteEntry); - } - palette[paletteEntryId] = type; - } - if (paletteSize == 1) { - // the same block everywhere - biomes.put(y, palette); - continue; - } - - // parse block states - long[] biomesSerialized = biomeTypesTag.getLongArray("data"); - if (biomesSerialized.length == 0) { - throw new InvalidFormatException("Biome data not present."); - } - - BiomeType[] chunkSectionBiomes = new BiomeType[64]; - biomes.put(y, chunkSectionBiomes); - - readBiomes(palette, biomesSerialized, chunkSectionBiomes); - } - } - } - - protected void readBiomes(BiomeType[] palette, long[] biomesSerialized, BiomeType[] chunkSectionBiomes) throws - InvalidFormatException { - PackedIntArrayReader reader = new PackedIntArrayReader(biomesSerialized, 64); - for (int biomePos = 0; biomePos < chunkSectionBiomes.length; biomePos++) { - int index = reader.get(biomePos); - if (index >= palette.length) { - throw new InvalidFormatException("Invalid biome table entry: " + index); - } - chunkSectionBiomes[biomePos] = palette[index]; - } - } - - @Override - public List getEntities() throws DataException { - if (entities == null) { - populateEntities(); - } - return entities; - } - - /** - * Used to load the biomes. - */ - private void populateEntities() throws DataException { - entities = new ArrayList<>(); - CompoundBinaryTag entityTag; - if (entityTagSupplier == null || (entityTag = entityTagSupplier.get()) == null) { - return; - } - ListBinaryTag tags = NbtUtils.getChildTag(entityTag, "Entities", BinaryTagTypes.LIST); - - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag t)) { - throw new InvalidFormatException("CompoundTag expected in Entities"); - } - - entities.add(new BaseEntity(EntityTypes.get(t.getString("id")), LazyReference.computed(t))); - } - - } - - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java index aabf38ac9..783045520 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java @@ -19,21 +19,19 @@ package com.sk89q.worldedit.world.chunk; -import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.nbt.BinaryTag; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.IntBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; import com.sk89q.worldedit.world.storage.InvalidFormatException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; import java.util.HashMap; import java.util.Map; @@ -43,24 +41,24 @@ import java.util.Map; */ public class OldChunk implements Chunk { - private final CompoundBinaryTag rootTag; + private final LinCompoundTag rootTag; private final byte[] blocks; private final byte[] data; private final int rootX; private final int rootZ; - private Map tileEntities; + private Map tileEntities; /** * Construct the chunk with a compound tag. * * @param tag the tag * @throws DataException if there is an error getting the chunk data - * @deprecated Use {@link #OldChunk(CompoundBinaryTag)} + * @deprecated Use {@link #OldChunk(LinCompoundTag)} */ @Deprecated public OldChunk(CompoundTag tag) throws DataException { - this(tag.asBinaryTag()); + this(tag.toLinTag()); } /** @@ -69,13 +67,13 @@ public class OldChunk implements Chunk { * @param tag the tag * @throws DataException if there is an error getting the chunk data */ - public OldChunk(CompoundBinaryTag tag) throws DataException { + public OldChunk(LinCompoundTag tag) throws DataException { rootTag = tag; - blocks = NbtUtils.getChildTag(rootTag, "Blocks", BinaryTagTypes.BYTE_ARRAY).value(); - data = NbtUtils.getChildTag(rootTag, "Data", BinaryTagTypes.BYTE_ARRAY).value(); - rootX = NbtUtils.getChildTag(rootTag, "xPos", BinaryTagTypes.INT).value(); - rootZ = NbtUtils.getChildTag(rootTag, "zPos", BinaryTagTypes.INT).value(); + blocks = rootTag.getTag("Blocks", LinTagType.byteArrayTag()).value(); + data = rootTag.getTag("Data", LinTagType.byteArrayTag()).value(); + rootX = rootTag.getTag("xPos", LinTagType.intTag()).value(); + rootZ = rootTag.getTag("zPos", LinTagType.intTag()).value(); int size = 16 * 16 * 128; if (blocks.length != size) { @@ -95,43 +93,39 @@ public class OldChunk implements Chunk { * @throws DataException if there is an error getting the chunk data */ private void populateTileEntities() throws DataException { - ListBinaryTag tags = NbtUtils.getChildTag(rootTag, "TileEntities", BinaryTagTypes.LIST); + LinListTag tags = rootTag.getTag("TileEntities", LinTagType.listTag()) + .asTypeChecked(LinTagType.compoundTag()); tileEntities = new HashMap<>(); - for (BinaryTag tag : tags) { - if (!(tag instanceof CompoundBinaryTag)) { - throw new InvalidFormatException("CompoundTag expected in TileEntities"); - } - - CompoundBinaryTag t = (CompoundBinaryTag) tag; - + for (LinCompoundTag t : tags.value()) { int x = 0; int y = 0; int z = 0; - CompoundBinaryTag.Builder values = CompoundBinaryTag.builder(); + LinCompoundTag.Builder values = LinCompoundTag.builder(); - for (String key : t.keySet()) { - BinaryTag value = t.get(key); + for (String key : t.value().keySet()) { + var value = t.value().get(key); switch (key) { - case "x": - if (value instanceof IntBinaryTag) { - x = ((IntBinaryTag) value).value(); + case "x" -> { + if (value instanceof LinIntTag v) { + x = v.valueAsInt(); } - break; - case "y": - if (value instanceof IntBinaryTag) { - y = ((IntBinaryTag) value).value(); + } + case "y" -> { + if (value instanceof LinIntTag v) { + y = v.valueAsInt(); } - break; - case "z": - if (value instanceof IntBinaryTag) { - z = ((IntBinaryTag) value).value(); + } + case "z" -> { + if (value instanceof LinIntTag v) { + z = v.valueAsInt(); } - break; - default: - break; + } + default -> { + // Do nothing. + } } values.put(key, value); @@ -151,26 +145,25 @@ public class OldChunk implements Chunk { * @return a tag * @throws DataException if there is an error getting the chunk data */ - private CompoundBinaryTag getBlockTileEntity(BlockVector3 position) throws DataException { + private LinCompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { if (tileEntities == null) { populateTileEntities(); } - CompoundBinaryTag values = tileEntities.get(position); - return values; + return tileEntities.get(position); } @Override public BaseBlock getBlock(BlockVector3 position) throws DataException { - if (position.getY() >= 128) { + if (position.y() >= 128) { return BlockTypes.VOID_AIR.getDefaultState().toBaseBlock(); } int id; int dataVal; - int x = position.getX() - rootX * 16; - int y = position.getY(); - int z = position.getZ() - rootZ * 16; + int x = position.x() - rootX * 16; + int y = position.y(); + int z = position.z() - rootZ * 16; int index = y + (z * 128 + (x * 128 * 16)); try { id = blocks[index]; @@ -197,13 +190,9 @@ public class OldChunk implements Chunk { return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - CompoundBinaryTag tileEntity = getBlockTileEntity(position); + LinCompoundTag tileEntity = getBlockTileEntity(position); - if (tileEntity != null) { - return state.toBaseBlock(tileEntity); - } - - return state.toBaseBlock(); + return state.toBaseBlock(tileEntity); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/package-info.java index ecb29c521..5ec273554 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/package-info.java @@ -1,7 +1,7 @@ /** * The following classes are FAWE additions: * - * @see com.sk89q.worldedit.world.chunk.AnvilChunk15 - * @see com.sk89q.worldedit.world.chunk.AnvilChunk17 + * {@link com.sk89q.worldedit.world.chunk.AnvilChunk15}, + * {@link com.sk89q.worldedit.world.chunk.AnvilChunk17} */ package com.sk89q.worldedit.world.chunk; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityType.java index 5a530c8a6..aba23b636 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityType.java @@ -23,13 +23,15 @@ import com.fastasyncworldedit.core.registry.RegistryItem; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.NamespacedRegistry; -//FAWE start - implements RegistryItem +//FAWE start - implements RegistryItem, not a record (internalId needs mutability) public class EntityType implements RegistryItem, Keyed { //FAWE end public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("entity type", true); + //FAWE start private final String id; + private int internalId; public EntityType(String id) { // If it has no namespace, assume minecraft. @@ -39,14 +41,28 @@ public class EntityType implements RegistryItem, Keyed { this.id = id; } + /** + * Gets the id of this entity type. + * + * @return the id + * @since 2.11.0 + */ + public String id() { + return this.id; + } + + /** + * Gets the id of this entity type. + * + * @return the id + * @deprecated use {@link #id()} + */ + @Deprecated(forRemoval = true, since = "2.11.0") @Override public String getId() { return this.id; } - //FAWE start - private int internalId; - @Override public void setInternalId(int internalId) { this.internalId = internalId; @@ -64,14 +80,15 @@ public class EntityType implements RegistryItem, Keyed { * @return The name, or ID */ public String getName() { - return getId(); + return id(); } @Override public String toString() { - return getId(); + return id(); } + //FAWE start @Override public int hashCode() { return this.id.hashCode(); @@ -81,5 +98,6 @@ public class EntityType implements RegistryItem, Keyed { public boolean equals(Object obj) { return obj instanceof EntityType && this.id.equals(((EntityType) obj).id); } + //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java index 4b650ac07..52044abdf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java @@ -35,6 +35,8 @@ public final class EntityTypes { @Nullable public static final EntityType AREA_EFFECT_CLOUD = get("minecraft:area_effect_cloud"); @Nullable + public static final EntityType ARMADILLO = get("minecraft:armadillo"); + @Nullable public static final EntityType ARMOR_STAND = get("minecraft:armor_stand"); @Nullable public static final EntityType ARROW = get("minecraft:arrow"); @@ -51,6 +53,12 @@ public final class EntityTypes { @Nullable public static final EntityType BOAT = get("minecraft:boat"); @Nullable + public static final EntityType BOGGED = get("minecraft:bogged"); + @Nullable + public static final EntityType BREEZE = get("minecraft:breeze"); + @Nullable + public static final EntityType BREEZE_WIND_CHARGE = get("minecraft:breeze_wind_charge"); + @Nullable public static final EntityType CAMEL = get("minecraft:camel"); @Nullable public static final EntityType CAT = get("minecraft:cat"); @@ -169,6 +177,8 @@ public final class EntityTypes { @Nullable public static final EntityType OCELOT = get("minecraft:ocelot"); @Nullable + public static final EntityType OMINOUS_ITEM_SPAWNER = get("minecraft:ominous_item_spawner"); + @Nullable public static final EntityType PAINTING = get("minecraft:painting"); @Nullable public static final EntityType PANDA = get("minecraft:panda"); @@ -259,6 +269,8 @@ public final class EntityTypes { @Nullable public static final EntityType WARDEN = get("minecraft:warden"); @Nullable + public static final EntityType WIND_CHARGE = get("minecraft:wind_charge"); + @Nullable public static final EntityType WITCH = get("minecraft:witch"); @Nullable public static final EntityType WITHER = get("minecraft:wither"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidCategories.java index 2788fdebe..79569156e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidCategories.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidCategories.java @@ -37,7 +37,7 @@ public final class FluidCategories { } public static FluidCategory register(final FluidCategory tag) { - return FluidCategory.REGISTRY.register(tag.getId(), tag); + return FluidCategory.REGISTRY.register(tag.id(), tag); } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidType.java index d62d13b51..1b191f07f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidType.java @@ -24,15 +24,15 @@ import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.NamespacedRegistry; /** - * Minecraft now has a 'fluid' system. This is a - * stub class to represent what it may be in the future. + * Minecraft now has a 'fluid' system. This is a stub class to represent what it may be in the future. */ -//FAWE start - implements RegistryItem +//FAWE start - implements RegistryItem, not a record (internalId needs mutability) public class FluidType implements RegistryItem, Keyed { //FAWE end public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("fluid type"); + //FAWE start private final String id; public FluidType(String id) { @@ -43,7 +43,19 @@ public class FluidType implements RegistryItem, Keyed { * Gets the ID of this block. * * @return The id + * @since 2.11.0 */ + public String id() { + return this.id; + } + + /** + * Gets the ID of this block. + * + * @return The id + * @deprecated use {@link #id()} + */ + @Deprecated(forRemoval = true, since = "2.11.0") @Override public String getId() { return this.id; @@ -67,7 +79,7 @@ public class FluidType implements RegistryItem, Keyed { @Override public String toString() { - return getId(); + return id(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidTypes.java index 18c43d8c8..dd5b0270e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/fluid/FluidTypes.java @@ -40,7 +40,7 @@ public final class FluidTypes { } public static FluidType register(final FluidType fluid) { - return FluidType.REGISTRY.register(fluid.getId(), fluid); + return FluidType.REGISTRY.register(fluid.id(), fluid); } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameMode.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameMode.java index 312caa3b5..94b7b7cfe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameMode.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameMode.java @@ -22,43 +22,21 @@ package com.sk89q.worldedit.world.gamemode; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.Registry; -public class GameMode implements Keyed { +public record GameMode(String id) implements Keyed { public static final Registry REGISTRY = new Registry<>("game mode"); - private final String id; - - public GameMode(String id) { - this.id = id; - } - - @Override - public String getId() { - return this.id; - } - /** * Gets the name of this game mode, or the ID if the name cannot be found. * * @return The name, or ID */ public String getName() { - return getId(); + return id(); } @Override public String toString() { - return getId(); + return id(); } - - @Override - public int hashCode() { - return this.id.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof GameMode && this.id.equals(((GameMode) obj).id); - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameModes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameModes.java index ce87f9ce7..b6d151ba8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameModes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/gamemode/GameModes.java @@ -36,7 +36,7 @@ public final class GameModes { } public static GameMode register(final GameMode gameMode) { - return GameMode.REGISTRY.register(gameMode.getId(), gameMode); + return GameMode.REGISTRY.register(gameMode.id(), gameMode); } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java index 3b6bdc6b6..466db6fdd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java @@ -29,28 +29,36 @@ public final class ItemCategories { public static final ItemCategory ACACIA_LOGS = get("minecraft:acacia_logs"); public static final ItemCategory ANVIL = get("minecraft:anvil"); + public static final ItemCategory ARMADILLO_FOOD = get("minecraft:armadillo_food"); public static final ItemCategory ARROWS = get("minecraft:arrows"); public static final ItemCategory AXES = get("minecraft:axes"); - public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items"); + public static final ItemCategory AXOLOTL_FOOD = get("minecraft:axolotl_food"); + @Deprecated public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items"); public static final ItemCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final ItemCategory BANNERS = get("minecraft:banners"); public static final ItemCategory BEACON_PAYMENT_ITEMS = get("minecraft:beacon_payment_items"); public static final ItemCategory BEDS = get("minecraft:beds"); + public static final ItemCategory BEE_FOOD = get("minecraft:bee_food"); public static final ItemCategory BIRCH_LOGS = get("minecraft:birch_logs"); public static final ItemCategory BOATS = get("minecraft:boats"); public static final ItemCategory BOOKSHELF_BOOKS = get("minecraft:bookshelf_books"); public static final ItemCategory BREAKS_DECORATED_POTS = get("minecraft:breaks_decorated_pots"); public static final ItemCategory BUTTONS = get("minecraft:buttons"); + public static final ItemCategory CAMEL_FOOD = get("minecraft:camel_food"); public static final ItemCategory CANDLES = get("minecraft:candles"); @Deprecated public static final ItemCategory CARPETS = get("minecraft:carpets"); + public static final ItemCategory CAT_FOOD = get("minecraft:cat_food"); public static final ItemCategory CHERRY_LOGS = get("minecraft:cherry_logs"); + public static final ItemCategory CHEST_ARMOR = get("minecraft:chest_armor"); public static final ItemCategory CHEST_BOATS = get("minecraft:chest_boats"); + public static final ItemCategory CHICKEN_FOOD = get("minecraft:chicken_food"); public static final ItemCategory CLUSTER_MAX_HARVESTABLES = get("minecraft:cluster_max_harvestables"); public static final ItemCategory COAL_ORES = get("minecraft:coal_ores"); public static final ItemCategory COALS = get("minecraft:coals"); public static final ItemCategory COMPASSES = get("minecraft:compasses"); public static final ItemCategory COMPLETES_FIND_TREE_TUTORIAL = get("minecraft:completes_find_tree_tutorial"); public static final ItemCategory COPPER_ORES = get("minecraft:copper_ores"); + public static final ItemCategory COW_FOOD = get("minecraft:cow_food"); public static final ItemCategory CREEPER_DROP_MUSIC_DISCS = get("minecraft:creeper_drop_music_discs"); public static final ItemCategory CREEPER_IGNITERS = get("minecraft:creeper_igniters"); public static final ItemCategory CRIMSON_STEMS = get("minecraft:crimson_stems"); @@ -61,44 +69,82 @@ public final class ItemCategories { public static final ItemCategory DIAMOND_ORES = get("minecraft:diamond_ores"); public static final ItemCategory DIRT = get("minecraft:dirt"); public static final ItemCategory DOORS = get("minecraft:doors"); + public static final ItemCategory DYEABLE = get("minecraft:dyeable"); public static final ItemCategory EMERALD_ORES = get("minecraft:emerald_ores"); + public static final ItemCategory ENCHANTABLE_ARMOR = get("minecraft:enchantable/armor"); + public static final ItemCategory ENCHANTABLE_BOW = get("minecraft:enchantable/bow"); + public static final ItemCategory ENCHANTABLE_CHEST_ARMOR = get("minecraft:enchantable/chest_armor"); + public static final ItemCategory ENCHANTABLE_CROSSBOW = get("minecraft:enchantable/crossbow"); + public static final ItemCategory ENCHANTABLE_DURABILITY = get("minecraft:enchantable/durability"); + public static final ItemCategory ENCHANTABLE_EQUIPPABLE = get("minecraft:enchantable/equippable"); + public static final ItemCategory ENCHANTABLE_FIRE_ASPECT = get("minecraft:enchantable/fire_aspect"); + public static final ItemCategory ENCHANTABLE_FISHING = get("minecraft:enchantable/fishing"); + public static final ItemCategory ENCHANTABLE_FOOT_ARMOR = get("minecraft:enchantable/foot_armor"); + public static final ItemCategory ENCHANTABLE_HEAD_ARMOR = get("minecraft:enchantable/head_armor"); + public static final ItemCategory ENCHANTABLE_LEG_ARMOR = get("minecraft:enchantable/leg_armor"); + public static final ItemCategory ENCHANTABLE_MINING = get("minecraft:enchantable/mining"); + public static final ItemCategory ENCHANTABLE_MINING_LOOT = get("minecraft:enchantable/mining_loot"); + public static final ItemCategory ENCHANTABLE_SHARP_WEAPON = get("minecraft:enchantable/sharp_weapon"); + public static final ItemCategory ENCHANTABLE_SWORD = get("minecraft:enchantable/sword"); + public static final ItemCategory ENCHANTABLE_TRIDENT = get("minecraft:enchantable/trident"); + public static final ItemCategory ENCHANTABLE_VANISHING = get("minecraft:enchantable/vanishing"); + public static final ItemCategory ENCHANTABLE_WEAPON = get("minecraft:enchantable/weapon"); public static final ItemCategory FENCE_GATES = get("minecraft:fence_gates"); public static final ItemCategory FENCES = get("minecraft:fences"); public static final ItemCategory FISHES = get("minecraft:fishes"); public static final ItemCategory FLOWERS = get("minecraft:flowers"); + public static final ItemCategory FOOT_ARMOR = get("minecraft:foot_armor"); public static final ItemCategory FOX_FOOD = get("minecraft:fox_food"); public static final ItemCategory FREEZE_IMMUNE_WEARABLES = get("minecraft:freeze_immune_wearables"); + public static final ItemCategory FROG_FOOD = get("minecraft:frog_food"); @Deprecated public static final ItemCategory FURNACE_MATERIALS = get("minecraft:furnace_materials"); + public static final ItemCategory GOAT_FOOD = get("minecraft:goat_food"); public static final ItemCategory GOLD_ORES = get("minecraft:gold_ores"); public static final ItemCategory HANGING_SIGNS = get("minecraft:hanging_signs"); + public static final ItemCategory HEAD_ARMOR = get("minecraft:head_armor"); public static final ItemCategory HOES = get("minecraft:hoes"); + public static final ItemCategory HOGLIN_FOOD = get("minecraft:hoglin_food"); + public static final ItemCategory HORSE_FOOD = get("minecraft:horse_food"); + public static final ItemCategory HORSE_TEMPT_ITEMS = get("minecraft:horse_tempt_items"); public static final ItemCategory IGNORED_BY_PIGLIN_BABIES = get("minecraft:ignored_by_piglin_babies"); public static final ItemCategory IRON_ORES = get("minecraft:iron_ores"); public static final ItemCategory JUNGLE_LOGS = get("minecraft:jungle_logs"); public static final ItemCategory LAPIS_ORES = get("minecraft:lapis_ores"); public static final ItemCategory LEAVES = get("minecraft:leaves"); public static final ItemCategory LECTERN_BOOKS = get("minecraft:lectern_books"); + public static final ItemCategory LEG_ARMOR = get("minecraft:leg_armor"); + public static final ItemCategory LLAMA_FOOD = get("minecraft:llama_food"); + public static final ItemCategory LLAMA_TEMPT_ITEMS = get("minecraft:llama_tempt_items"); public static final ItemCategory LOGS = get("minecraft:logs"); public static final ItemCategory LOGS_THAT_BURN = get("minecraft:logs_that_burn"); public static final ItemCategory MANGROVE_LOGS = get("minecraft:mangrove_logs"); + public static final ItemCategory MEAT = get("minecraft:meat"); public static final ItemCategory MUSIC_DISCS = get("minecraft:music_discs"); public static final ItemCategory NON_FLAMMABLE_WOOD = get("minecraft:non_flammable_wood"); public static final ItemCategory NOTEBLOCK_TOP_INSTRUMENTS = get("minecraft:noteblock_top_instruments"); public static final ItemCategory OAK_LOGS = get("minecraft:oak_logs"); @Deprecated public static final ItemCategory OCCLUDES_VIBRATION_SIGNALS = get("minecraft:occludes_vibration_signals"); + public static final ItemCategory OCELOT_FOOD = get("minecraft:ocelot_food"); @Deprecated public static final ItemCategory OVERWORLD_NATURAL_LOGS = get("minecraft:overworld_natural_logs"); + public static final ItemCategory PANDA_FOOD = get("minecraft:panda_food"); + public static final ItemCategory PARROT_FOOD = get("minecraft:parrot_food"); + public static final ItemCategory PARROT_POISONOUS_FOOD = get("minecraft:parrot_poisonous_food"); public static final ItemCategory PICKAXES = get("minecraft:pickaxes"); + public static final ItemCategory PIG_FOOD = get("minecraft:pig_food"); public static final ItemCategory PIGLIN_FOOD = get("minecraft:piglin_food"); public static final ItemCategory PIGLIN_LOVED = get("minecraft:piglin_loved"); public static final ItemCategory PIGLIN_REPELLENTS = get("minecraft:piglin_repellents"); public static final ItemCategory PLANKS = get("minecraft:planks"); + public static final ItemCategory RABBIT_FOOD = get("minecraft:rabbit_food"); public static final ItemCategory RAILS = get("minecraft:rails"); public static final ItemCategory REDSTONE_ORES = get("minecraft:redstone_ores"); public static final ItemCategory SAND = get("minecraft:sand"); public static final ItemCategory SAPLINGS = get("minecraft:saplings"); + public static final ItemCategory SHEEP_FOOD = get("minecraft:sheep_food"); public static final ItemCategory SHOVELS = get("minecraft:shovels"); public static final ItemCategory SIGNS = get("minecraft:signs"); + public static final ItemCategory SKULLS = get("minecraft:skulls"); public static final ItemCategory SLABS = get("minecraft:slabs"); public static final ItemCategory SMALL_FLOWERS = get("minecraft:small_flowers"); public static final ItemCategory SMELTS_TO_GLASS = get("minecraft:smelts_to_glass"); @@ -110,18 +156,22 @@ public final class ItemCategories { public static final ItemCategory STONE_BUTTONS = get("minecraft:stone_buttons"); public static final ItemCategory STONE_CRAFTING_MATERIALS = get("minecraft:stone_crafting_materials"); public static final ItemCategory STONE_TOOL_MATERIALS = get("minecraft:stone_tool_materials"); + public static final ItemCategory STRIDER_FOOD = get("minecraft:strider_food"); + public static final ItemCategory STRIDER_TEMPT_ITEMS = get("minecraft:strider_tempt_items"); public static final ItemCategory SWORDS = get("minecraft:swords"); public static final ItemCategory TALL_FLOWERS = get("minecraft:tall_flowers"); public static final ItemCategory TERRACOTTA = get("minecraft:terracotta"); - public static final ItemCategory TOOLS = get("minecraft:tools"); + @Deprecated public static final ItemCategory TOOLS = get("minecraft:tools"); public static final ItemCategory TRAPDOORS = get("minecraft:trapdoors"); public static final ItemCategory TRIM_MATERIALS = get("minecraft:trim_materials"); public static final ItemCategory TRIM_TEMPLATES = get("minecraft:trim_templates"); public static final ItemCategory TRIMMABLE_ARMOR = get("minecraft:trimmable_armor"); + public static final ItemCategory TURTLE_FOOD = get("minecraft:turtle_food"); public static final ItemCategory VILLAGER_PLANTABLE_SEEDS = get("minecraft:villager_plantable_seeds"); public static final ItemCategory WALLS = get("minecraft:walls"); public static final ItemCategory WARPED_STEMS = get("minecraft:warped_stems"); public static final ItemCategory WART_BLOCKS = get("minecraft:wart_blocks"); + public static final ItemCategory WOLF_FOOD = get("minecraft:wolf_food"); public static final ItemCategory WOODEN_BUTTONS = get("minecraft:wooden_buttons"); public static final ItemCategory WOODEN_DOORS = get("minecraft:wooden_doors"); public static final ItemCategory WOODEN_FENCES = get("minecraft:wooden_fences"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java index 5a1e7653f..e7a72b3c9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java @@ -42,19 +42,21 @@ public class ItemType implements RegistryItem, Keyed { public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("item type", true); private final String id; - @SuppressWarnings("deprecation") + @SuppressWarnings({"deprecation", "this-escape"}) private transient final LazyReference name = LazyReference.from(() -> { String name = GuavaUtil.firstNonNull( WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) .getRegistries().getItemRegistry().getName(this), "" ); - return name.isEmpty() ? getId() : name; + return name.isEmpty() ? id() : name; }); + @SuppressWarnings("this-escape") private transient final LazyReference richName = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) .getRegistries().getItemRegistry().getRichName(this) ); + @SuppressWarnings("this-escape") private transient final LazyReference itemMaterial = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) .getRegistries().getItemRegistry().getMaterial(this) @@ -74,12 +76,12 @@ public class ItemType implements RegistryItem, Keyed { } @Override - public String getId() { + public String id() { return this.id; } //FAWE start - private int internalId; + private transient int internalId; @Override public void setInternalId(int internalId) { @@ -151,7 +153,7 @@ public class ItemType implements RegistryItem, Keyed { @Override public String toString() { - return getId(); + return id(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java index 663cf5c61..f3cd6d0cc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java @@ -105,6 +105,10 @@ public final class ItemTypes { @Nullable public static final ItemType ARMOR_STAND = init(); @Nullable + public static final ItemType ARMADILLO_SCUTE = init(); + @Nullable + public static final ItemType ARMADILLO_SPAWN_EGG = init(); + @Nullable public static final ItemType ARMS_UP_POTTERY_SHERD = init(); @Nullable public static final ItemType ARROW = init(); @@ -297,6 +301,10 @@ public final class ItemTypes { @Nullable public static final ItemType BLUE_WOOL = init(); @Nullable + public static final ItemType BOGGED_SPAWN_EGG = init(); + @Nullable + public static final ItemType BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = init(); + @Nullable public static final ItemType BONE = init(); @Nullable public static final ItemType BONE_BLOCK = init(); @@ -319,6 +327,10 @@ public final class ItemTypes { @Nullable public static final ItemType BREAD = init(); @Nullable + public static final ItemType BREEZE_ROD = init(); + @Nullable + public static final ItemType BREEZE_SPAWN_EGG = init(); + @Nullable public static final ItemType BREWER_POTTERY_SHERD = init(); @Nullable public static final ItemType BREWING_STAND = init(); @@ -468,6 +480,8 @@ public final class ItemTypes { @Nullable public static final ItemType CHISELED_BOOKSHELF = init(); @Nullable + public static final ItemType CHISELED_COPPER = init(); + @Nullable public static final ItemType CHISELED_DEEPSLATE = init(); @Nullable public static final ItemType CHISELED_NETHER_BRICKS = init(); @@ -482,6 +496,10 @@ public final class ItemTypes { @Nullable public static final ItemType CHISELED_STONE_BRICKS = init(); @Nullable + public static final ItemType CHISELED_TUFF = init(); + @Nullable + public static final ItemType CHISELED_TUFF_BRICKS = init(); + @Nullable public static final ItemType CHORUS_FLOWER = init(); @Nullable public static final ItemType CHORUS_FRUIT = init(); @@ -560,10 +578,18 @@ public final class ItemTypes { @Nullable public static final ItemType COPPER_BLOCK = init(); @Nullable + public static final ItemType COPPER_BULB = init(); + @Nullable + public static final ItemType COPPER_DOOR = init(); + @Nullable + public static final ItemType COPPER_GRATE = init(); + @Nullable public static final ItemType COPPER_INGOT = init(); @Nullable public static final ItemType COPPER_ORE = init(); @Nullable + public static final ItemType COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType CORNFLOWER = init(); @Nullable public static final ItemType COW_SPAWN_EGG = init(); @@ -578,6 +604,8 @@ public final class ItemTypes { @Nullable public static final ItemType CRACKED_STONE_BRICKS = init(); @Nullable + public static final ItemType CRAFTER = init(); + @Nullable public static final ItemType CRAFTING_TABLE = init(); @Nullable public static final ItemType CREEPER_BANNER_PATTERN = init(); @@ -903,8 +931,18 @@ public final class ItemTypes { @Nullable public static final ItemType EXPLORER_POTTERY_SHERD = init(); @Nullable + public static final ItemType EXPOSED_CHISELED_COPPER = init(); + @Nullable public static final ItemType EXPOSED_COPPER = init(); @Nullable + public static final ItemType EXPOSED_COPPER_BULB = init(); + @Nullable + public static final ItemType EXPOSED_COPPER_DOOR = init(); + @Nullable + public static final ItemType EXPOSED_COPPER_GRATE = init(); + @Nullable + public static final ItemType EXPOSED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType EXPOSED_CUT_COPPER = init(); @Nullable public static final ItemType EXPOSED_CUT_COPPER_SLAB = init(); @@ -943,6 +981,12 @@ public final class ItemTypes { @Nullable public static final ItemType FLINT_AND_STEEL = init(); @Nullable + public static final ItemType FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = init(); + @Nullable + public static final ItemType FLOW_BANNER_PATTERN = init(); + @Nullable + public static final ItemType FLOW_POTTERY_SHERD = init(); + @Nullable public static final ItemType FLOWER_BANNER_PATTERN = init(); @Nullable public static final ItemType FLOWER_POT = init(); @@ -1036,7 +1080,7 @@ public final class ItemTypes { public static final ItemType GRANITE_STAIRS = init(); @Nullable public static final ItemType GRANITE_WALL = init(); - @Nullable + @Nullable @Deprecated public static final ItemType GRASS = init(); @Nullable public static final ItemType GRASS_BLOCK = init(); @@ -1104,6 +1148,10 @@ public final class ItemTypes { @Nullable public static final ItemType GUNPOWDER = init(); @Nullable + public static final ItemType GUSTER_BANNER_PATTERN = init(); + @Nullable + public static final ItemType GUSTER_POTTERY_SHERD = init(); + @Nullable public static final ItemType HANGING_ROOTS = init(); @Nullable public static final ItemType HAY_BLOCK = init(); @@ -1114,6 +1162,8 @@ public final class ItemTypes { @Nullable public static final ItemType HEARTBREAK_POTTERY_SHERD = init(); @Nullable + public static final ItemType HEAVY_CORE = init(); + @Nullable public static final ItemType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); @Nullable public static final ItemType HOGLIN_SPAWN_EGG = init(); @@ -1376,6 +1426,8 @@ public final class ItemTypes { @Nullable public static final ItemType LOOM = init(); @Nullable + public static final ItemType MACE = init(); + @Nullable public static final ItemType MAGENTA_BANNER = init(); @Nullable public static final ItemType MAGENTA_BED = init(); @@ -1640,6 +1692,10 @@ public final class ItemTypes { @Nullable public static final ItemType OCHRE_FROGLIGHT = init(); @Nullable + public static final ItemType OMINOUS_BOTTLE = init(); + @Nullable + public static final ItemType OMINOUS_TRIAL_KEY = init(); + @Nullable public static final ItemType ORANGE_BANNER = init(); @Nullable public static final ItemType ORANGE_BED = init(); @@ -1670,8 +1726,18 @@ public final class ItemTypes { @Nullable public static final ItemType OXEYE_DAISY = init(); @Nullable + public static final ItemType OXIDIZED_CHISELED_COPPER = init(); + @Nullable public static final ItemType OXIDIZED_COPPER = init(); @Nullable + public static final ItemType OXIDIZED_COPPER_BULB = init(); + @Nullable + public static final ItemType OXIDIZED_COPPER_DOOR = init(); + @Nullable + public static final ItemType OXIDIZED_COPPER_GRATE = init(); + @Nullable + public static final ItemType OXIDIZED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType OXIDIZED_CUT_COPPER = init(); @Nullable public static final ItemType OXIDIZED_CUT_COPPER_SLAB = init(); @@ -1808,6 +1874,14 @@ public final class ItemTypes { @Nullable public static final ItemType POLISHED_GRANITE_STAIRS = init(); @Nullable + public static final ItemType POLISHED_TUFF = init(); + @Nullable + public static final ItemType POLISHED_TUFF_SLAB = init(); + @Nullable + public static final ItemType POLISHED_TUFF_STAIRS = init(); + @Nullable + public static final ItemType POLISHED_TUFF_WALL = init(); + @Nullable public static final ItemType POPPED_CHORUS_FRUIT = init(); @Nullable public static final ItemType POPPY = init(); @@ -2029,6 +2103,8 @@ public final class ItemTypes { @Nullable public static final ItemType SCAFFOLDING = init(); @Nullable + public static final ItemType SCRAPE_POTTERY_SHERD = init(); + @Nullable public static final ItemType SCULK = init(); @Nullable public static final ItemType SCULK_CATALYST = init(); @@ -2039,6 +2115,7 @@ public final class ItemTypes { @Nullable public static final ItemType SCULK_VEIN = init(); @Nullable + @Deprecated public static final ItemType SCUTE = init(); @Nullable public static final ItemType SEA_LANTERN = init(); @@ -2061,6 +2138,8 @@ public final class ItemTypes { @Nullable public static final ItemType SHIELD = init(); @Nullable + public static final ItemType SHORT_GRASS = init(); + @Nullable public static final ItemType SHROOMLIGHT = init(); @Nullable public static final ItemType SHULKER_BOX = init(); @@ -2336,6 +2415,10 @@ public final class ItemTypes { @Nullable public static final ItemType TRAPPED_CHEST = init(); @Nullable + public static final ItemType TRIAL_KEY = init(); + @Nullable + public static final ItemType TRIAL_SPAWNER = init(); + @Nullable public static final ItemType TRIDENT = init(); @Nullable public static final ItemType TRIPWIRE_HOOK = init(); @@ -2354,14 +2437,32 @@ public final class ItemTypes { @Nullable public static final ItemType TUFF = init(); @Nullable + public static final ItemType TUFF_BRICK_SLAB = init(); + @Nullable + public static final ItemType TUFF_BRICK_STAIRS = init(); + @Nullable + public static final ItemType TUFF_BRICK_WALL = init(); + @Nullable + public static final ItemType TUFF_BRICKS = init(); + @Nullable + public static final ItemType TUFF_SLAB = init(); + @Nullable + public static final ItemType TUFF_STAIRS = init(); + @Nullable + public static final ItemType TUFF_WALL = init(); + @Nullable public static final ItemType TURTLE_EGG = init(); @Nullable public static final ItemType TURTLE_HELMET = init(); @Nullable + public static final ItemType TURTLE_SCUTE = init(); + @Nullable public static final ItemType TURTLE_SPAWN_EGG = init(); @Nullable public static final ItemType TWISTING_VINES = init(); @Nullable + public static final ItemType VAULT = init(); + @Nullable public static final ItemType VERDANT_FROGLIGHT = init(); @Nullable public static final ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = init(); @@ -2418,32 +2519,72 @@ public final class ItemTypes { @Nullable public static final ItemType WATER_BUCKET = init(); @Nullable + public static final ItemType WAXED_CHISELED_COPPER = init(); + @Nullable public static final ItemType WAXED_COPPER_BLOCK = init(); @Nullable + public static final ItemType WAXED_COPPER_BULB = init(); + @Nullable + public static final ItemType WAXED_COPPER_DOOR = init(); + @Nullable + public static final ItemType WAXED_COPPER_GRATE = init(); + @Nullable + public static final ItemType WAXED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType WAXED_CUT_COPPER = init(); @Nullable public static final ItemType WAXED_CUT_COPPER_SLAB = init(); @Nullable public static final ItemType WAXED_CUT_COPPER_STAIRS = init(); @Nullable + public static final ItemType WAXED_EXPOSED_CHISELED_COPPER = init(); + @Nullable public static final ItemType WAXED_EXPOSED_COPPER = init(); @Nullable + public static final ItemType WAXED_EXPOSED_COPPER_BULB = init(); + @Nullable + public static final ItemType WAXED_EXPOSED_COPPER_DOOR = init(); + @Nullable + public static final ItemType WAXED_EXPOSED_COPPER_GRATE = init(); + @Nullable + public static final ItemType WAXED_EXPOSED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType WAXED_EXPOSED_CUT_COPPER = init(); @Nullable public static final ItemType WAXED_EXPOSED_CUT_COPPER_SLAB = init(); @Nullable public static final ItemType WAXED_EXPOSED_CUT_COPPER_STAIRS = init(); @Nullable + public static final ItemType WAXED_OXIDIZED_CHISELED_COPPER = init(); + @Nullable public static final ItemType WAXED_OXIDIZED_COPPER = init(); @Nullable + public static final ItemType WAXED_OXIDIZED_COPPER_BULB = init(); + @Nullable + public static final ItemType WAXED_OXIDIZED_COPPER_DOOR = init(); + @Nullable + public static final ItemType WAXED_OXIDIZED_COPPER_GRATE = init(); + @Nullable + public static final ItemType WAXED_OXIDIZED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType WAXED_OXIDIZED_CUT_COPPER = init(); @Nullable public static final ItemType WAXED_OXIDIZED_CUT_COPPER_SLAB = init(); @Nullable public static final ItemType WAXED_OXIDIZED_CUT_COPPER_STAIRS = init(); @Nullable + public static final ItemType WAXED_WEATHERED_CHISELED_COPPER = init(); + @Nullable public static final ItemType WAXED_WEATHERED_COPPER = init(); @Nullable + public static final ItemType WAXED_WEATHERED_COPPER_BULB = init(); + @Nullable + public static final ItemType WAXED_WEATHERED_COPPER_DOOR = init(); + @Nullable + public static final ItemType WAXED_WEATHERED_COPPER_GRATE = init(); + @Nullable + public static final ItemType WAXED_WEATHERED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType WAXED_WEATHERED_CUT_COPPER = init(); @Nullable public static final ItemType WAXED_WEATHERED_CUT_COPPER_SLAB = init(); @@ -2452,8 +2593,18 @@ public final class ItemTypes { @Nullable public static final ItemType WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = init(); @Nullable + public static final ItemType WEATHERED_CHISELED_COPPER = init(); + @Nullable public static final ItemType WEATHERED_COPPER = init(); @Nullable + public static final ItemType WEATHERED_COPPER_BULB = init(); + @Nullable + public static final ItemType WEATHERED_COPPER_DOOR = init(); + @Nullable + public static final ItemType WEATHERED_COPPER_GRATE = init(); + @Nullable + public static final ItemType WEATHERED_COPPER_TRAPDOOR = init(); + @Nullable public static final ItemType WEATHERED_CUT_COPPER = init(); @Nullable public static final ItemType WEATHERED_CUT_COPPER_SLAB = init(); @@ -2498,6 +2649,8 @@ public final class ItemTypes { @Nullable public static final ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = init(); @Nullable + public static final ItemType WIND_CHARGE = init(); + @Nullable public static final ItemType WITCH_SPAWN_EGG = init(); @Nullable public static final ItemType WITHER_ROSE = init(); @@ -2508,6 +2661,8 @@ public final class ItemTypes { @Nullable public static final ItemType WITHER_SPAWN_EGG = init(); @Nullable + public static final ItemType WOLF_ARMOR = init(); + @Nullable public static final ItemType WOLF_SPAWN_EGG = init(); @Nullable public static final ItemType WOODEN_AXE = init(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java index c8baea757..243acb171 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import javax.annotation.Nullable; @@ -185,7 +186,19 @@ public interface BlockMaterial { * @return default tile entity data */ @Nullable - CompoundTag getDefaultTile(); + default CompoundTag getDefaultTile() { + final FaweCompoundTag faweCompoundTag = defaultTile(); + if (faweCompoundTag == null) { + return null; + } + return new CompoundTag(faweCompoundTag.linTag()); + } + + /** + * {@return the default tile associated with this material, if any} + * @since 2.11.2 + */ + @Nullable FaweCompoundTag defaultTile(); /** * Get the map color. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java index 3f7181397..11663a4f1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java @@ -41,7 +41,7 @@ public class BundledBlockRegistry implements BlockRegistry { @Override public Component getRichName(BlockType blockType) { - BundledBlockData.BlockEntry blockEntry = BundledBlockData.getInstance().findById(blockType.getId()); + BundledBlockData.BlockEntry blockEntry = BundledBlockData.getInstance().findById(blockType.id()); if (blockEntry != null) { // This is more likely to be "right", but not translated // Some vanilla MC blocks have overrides so we need this name here @@ -50,7 +50,7 @@ public class BundledBlockRegistry implements BlockRegistry { return TextComponent.of(blockEntry.localizedName); } return Caption.of( - TranslationManager.makeTranslationKey("block", blockType.getId()) + TranslationManager.makeTranslationKey("block", blockType.id()) ); } @@ -60,14 +60,14 @@ public class BundledBlockRegistry implements BlockRegistry { // dumb_intellij.jpg - Ok?? @SuppressWarnings("deprecation") public String getName(BlockType blockType) { - BundledBlockData.BlockEntry blockEntry = BundledBlockData.getInstance().findById(blockType.getId()); + BundledBlockData.BlockEntry blockEntry = BundledBlockData.getInstance().findById(blockType.id()); return blockEntry != null ? blockEntry.localizedName : null; } @Nullable @Override public BlockMaterial getMaterial(BlockType blockType) { - return new PassthroughBlockMaterial(BundledBlockData.getInstance().getMaterialById(blockType.getId())); + return new PassthroughBlockMaterial(BundledBlockData.getInstance().getMaterialById(blockType.id())); } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemData.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemData.java index 80a1e5e5b..126a0a967 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemData.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemData.java @@ -55,7 +55,6 @@ public final class BundledItemData { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static BundledItemData INSTANCE; - private final ResourceLoader resourceLoader; private final Map idMap = new HashMap<>(); @@ -63,12 +62,6 @@ public final class BundledItemData { * Create a new instance. */ private BundledItemData() { - this.resourceLoader = WorldEdit - .getInstance() - .getPlatformManager() - .queryCapability(Capability.CONFIGURATION) - .getResourceLoader(); - try { loadFromResource(); } catch (Throwable e) { @@ -85,28 +78,10 @@ public final class BundledItemData { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter()); Gson gson = gsonBuilder.create(); - URL url = null; - final int dataVersion = WorldEdit - .getInstance() - .getPlatformManager() - .queryCapability(Capability.WORLD_EDITING) - .getDataVersion(); - if (dataVersion >= Constants.DATA_VERSION_MC_1_17) { - url = resourceLoader.getResource(BundledBlockData.class, "items.117.json"); - } else if (dataVersion >= Constants.DATA_VERSION_MC_1_16) { - url = resourceLoader.getResource(BundledBlockData.class, "items.116.json"); - } else if (dataVersion >= Constants.DATA_VERSION_MC_1_15) { - url = resourceLoader.getResource(BundledBlockData.class, "items.115.json"); - } - if (url == null) { - url = resourceLoader.getResource(BundledBlockData.class, "items.json"); - } - if (url == null) { - throw new IOException("Could not find items.json"); - } + URL url = BundledRegistries.loadRegistry("items"); + LOGGER.debug("Using {} for bundled item data.", url); String data = Resources.toString(url, Charset.defaultCharset()); - List entries = gson.fromJson(data, new TypeToken>() { - }.getType()); + List entries = gson.fromJson(data, new TypeToken>() {}.getType()); for (ItemEntry entry : entries) { idMap.put(entry.id, entry); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemRegistry.java index 2e1d42121..53a707821 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledItemRegistry.java @@ -34,7 +34,7 @@ import javax.annotation.Nullable; public class BundledItemRegistry implements ItemRegistry { private BundledItemData.ItemEntry getEntryById(ItemType itemType) { - return BundledItemData.getInstance().findById(itemType.getId()); + return BundledItemData.getInstance().findById(itemType.id()); } @Override @@ -48,7 +48,7 @@ public class BundledItemRegistry implements ItemRegistry { return TextComponent.of(itemEntry.localizedName); } return Caption.of( - TranslationManager.makeTranslationKey("item", itemType.getId()) + TranslationManager.makeTranslationKey("item", itemType.id()) ); } @@ -62,7 +62,7 @@ public class BundledItemRegistry implements ItemRegistry { if (itemEntry != null) { String localized = itemEntry.localizedName; if (localized.equals("Air")) { - String id = itemType.getId(); + String id = itemType.id(); int c = id.indexOf(':'); return c < 0 ? id : id.substring(c + 1); } @@ -74,7 +74,7 @@ public class BundledItemRegistry implements ItemRegistry { @Nullable @Override public ItemMaterial getMaterial(ItemType itemType) { - return new PassthroughItemMaterial(BundledItemData.getInstance().getMaterialById(itemType.getId())); + return new PassthroughItemMaterial(BundledItemData.getInstance().getMaterialById(itemType.id())); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledRegistries.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledRegistries.java index 26113dd6e..945801ee9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledRegistries.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledRegistries.java @@ -43,11 +43,9 @@ public class BundledRegistries implements Registries { static { TreeRangeMap versionMap = TreeRangeMap.create(); - versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_16), "116"); - versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_17), "117"); - // 1.18 did have one item change, but we didn't get it. It's fine. - versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_19), "119"); versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_20), "120"); + versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_21), "121"); + versionMap.put(Range.atLeast(Constants.DATA_VERSION_MC_1_21_3), "1213"); VERSION_MAP = ImmutableRangeMap.copyOf(versionMap); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/CategoryRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/CategoryRegistry.java index c52c507b9..dade2d193 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/CategoryRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/CategoryRegistry.java @@ -38,7 +38,7 @@ public interface CategoryRegistry { Set getCategorisedByName(String category); default Set getAll(final Category category) { - return getCategorisedByName(category.getId()); + return getCategorisedByName(category.id()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/ItemMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/ItemMaterial.java index 19fe653fc..45071859c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/ItemMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/ItemMaterial.java @@ -19,20 +19,53 @@ package com.sk89q.worldedit.world.registry; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; + public interface ItemMaterial { + /** + * Gets the the maximum quantity of this item that can be in a single stack. + * + * @return the maximum quantity + * @deprecated Use {@link #maxStackSize()} instead. + */ + @Deprecated(forRemoval = true, since = "2.11.0") + default int getMaxStackSize() { + return maxStackSize(); + } /** * Gets the the maximum quantity of this item that can be in a single stack. * * @return the maximum quantity + * @since 2.11.0 */ - int getMaxStackSize(); + @NonAbstractForCompatibility(delegateName = "getMaxStackSize", delegateParams = {}) + default int maxStackSize() { + DeprecationUtil.checkDelegatingOverride(getClass()); + return getMaxStackSize(); + } /** * Gets the the maximum damage this item can take before being broken. * * @return the maximum damage, or 0 if not applicable + * @deprecated Use {@link #maxDamage()} instead. */ - int getMaxDamage(); + @Deprecated(forRemoval = true, since = "2.11.0") + default int getMaxDamage() { + return maxDamage(); + } + /** + * Gets the the maximum damage this item can take before being broken. + * + * @return the maximum damage, or 0 if not applicable + * @since 2.11.0 + */ + @NonAbstractForCompatibility(delegateName = "getMaxDamage", delegateParams = {}) + default int maxDamage() { + DeprecationUtil.checkDelegatingOverride(getClass()); + return getMaxDamage(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/NullBiomeRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/NullBiomeRegistry.java index 346c94477..19fdd3b88 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/NullBiomeRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/NullBiomeRegistry.java @@ -41,7 +41,7 @@ public class NullBiomeRegistry implements BiomeRegistry { @Override public Component getRichName(BiomeType biomeType) { return Caption.of( - TranslationManager.makeTranslationKey("biome", biomeType.getId()) + TranslationManager.makeTranslationKey("biome", biomeType.id()) ); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java index 95743b80a..28b09a30e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import javax.annotation.Nullable; @@ -168,5 +169,11 @@ public class PassthroughBlockMaterial implements BlockMaterial { public CompoundTag getDefaultTile() { return blockMaterial.getDefaultTile(); } + + @Override + public @Nullable FaweCompoundTag defaultTile() { + return blockMaterial.defaultTile(); + } + //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughItemMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughItemMaterial.java index 681add8cc..e5dac8a7f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughItemMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughItemMaterial.java @@ -34,13 +34,13 @@ public class PassthroughItemMaterial implements ItemMaterial { } @Override - public int getMaxStackSize() { - return itemMaterial.getMaxStackSize(); + public int maxStackSize() { + return itemMaterial.maxStackSize(); } @Override - public int getMaxDamage() { - return itemMaterial.getMaxDamage(); + public int maxDamage() { + return itemMaterial.maxDamage(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java index 763ac81bc..737510816 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java @@ -19,8 +19,11 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; +import javax.annotation.Nullable; + class SimpleBlockMaterial implements BlockMaterial { private boolean isAir; @@ -251,8 +254,12 @@ class SimpleBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { - return tile; + public @Nullable FaweCompoundTag defaultTile() { + // this implementation is very lazy, but SimpleBlockMaterial isn't really used anyway + if (tile != null) { + return FaweCompoundTag.of(tile.toLinTag()); + } + return null; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleItemMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleItemMaterial.java index 40ed03515..9e552e18a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleItemMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleItemMaterial.java @@ -19,24 +19,6 @@ package com.sk89q.worldedit.world.registry; -public class SimpleItemMaterial implements ItemMaterial { - - private final int maxStackSize; - private final int maxDamage; - - public SimpleItemMaterial(int maxStackSize, int maxDamage) { - this.maxStackSize = maxStackSize; - this.maxDamage = maxDamage; - } - - @Override - public int getMaxStackSize() { - return maxStackSize; - } - - @Override - public int getMaxDamage() { - return maxDamage; - } +public record SimpleItemMaterial(int maxStackSize, int maxDamage) implements ItemMaterial { } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRestore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRestore.java index 0d86679cf..df506c67a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRestore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRestore.java @@ -28,12 +28,15 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.chunk.Chunk; import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.MissingChunkException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; import java.io.IOException; import java.util.ArrayList; @@ -114,9 +117,9 @@ public class SnapshotRestore { // First, we need to group points by chunk so that we only need // to keep one chunk in memory at any given moment - for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) { - for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) { + for (int x = min.x(); x <= max.x(); ++x) { + for (int y = min.y(); y <= max.y(); ++y) { + for (int z = min.z(); z <= max.z(); ++z) { BlockVector3 pos = BlockVector3.at(x, y, z); checkAndAddBlock(pos); } @@ -185,7 +188,7 @@ public class SnapshotRestore { try { editSession.setBlock(pos, chunk.getBlock(pos)); //FAWE start - biome and entity restore - if (restoreBiomes && (pos.getX() & 3) == 0 && (pos.getY() & 3) == 0 && (pos.getZ() & 3) == 0) { + if (restoreBiomes && (pos.x() & 3) == 0 && (pos.y() & 3) == 0 && (pos.z() & 3) == 0) { editSession.setBiome(pos, chunk.getBiome(pos)); } //FAWE end @@ -197,14 +200,14 @@ public class SnapshotRestore { if (restoreEntities) { try { for (BaseEntity entity : chunk.getEntities()) { - CompoundBinaryTag tag = entity.getNbtReference().getValue(); - ListBinaryTag pos = tag.getList("Pos"); - ListBinaryTag rotation = tag.getList("Rotation"); - double x = pos.getDouble(0); - double y = pos.getDouble(1); - double z = pos.getDouble(2); - float yRot = rotation.getFloat(0); - float xRot = rotation.getFloat(1); + LinCompoundTag tag = entity.getNbtReference().getValue(); + LinListTag pos = tag.getListTag("Pos", LinTagType.doubleTag()); + LinListTag rotation = tag.getListTag("Rotation", LinTagType.floatTag()); + double x = pos.get(0).value(); + double y = pos.get(1).value(); + double z = pos.get(2).value(); + float yRot = rotation.get(0).value(); + float xRot = rotation.get(1).value(); Location location = new Location(editSession.getWorld(), x, y, z, yRot, xRot); BlockVector3 blockVector3 = BlockVector3.at(x, y, z); if (region.contains(blockVector3) && (editSession.getMask() == null diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/experimental/SnapshotRestore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/experimental/SnapshotRestore.java index 9493fc76f..39d4fb07b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/experimental/SnapshotRestore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/experimental/SnapshotRestore.java @@ -27,13 +27,15 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.nbt.BinaryTagTypes; -import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; -import com.sk89q.worldedit.util.nbt.ListBinaryTag; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.chunk.Chunk; import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.MissingChunkException; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinTagType; import java.io.IOException; import java.util.ArrayList; @@ -109,9 +111,9 @@ public class SnapshotRestore { // First, we need to group points by chunk so that we only need // to keep one chunk in memory at any given moment - for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) { - for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) { + for (int x = min.x(); x <= max.x(); ++x) { + for (int y = min.y(); y <= max.y(); ++y) { + for (int z = min.z(); z <= max.z(); ++z) { BlockVector3 pos = BlockVector3.at(x, y, z); checkAndAddBlock(pos); } @@ -181,7 +183,7 @@ public class SnapshotRestore { try { editSession.setBlock(pos, chunk.getBlock(pos)); //FAWE start - biome and entity restore - if (restoreBiomes && (pos.getX() & 3) == 0 && (pos.getY() & 3) == 0 && (pos.getZ() & 3) == 0) { + if (restoreBiomes && (pos.x() & 3) == 0 && (pos.y() & 3) == 0 && (pos.z() & 3) == 0) { editSession.setBiome(pos, chunk.getBiome(pos)); } //FAWE end @@ -193,14 +195,14 @@ public class SnapshotRestore { if (restoreEntities) { try { for (BaseEntity entity : chunk.getEntities()) { - CompoundBinaryTag tag = entity.getNbtReference().getValue(); - ListBinaryTag pos = tag.getList("Pos", BinaryTagTypes.LIST); - ListBinaryTag rotation = tag.getList("Rotation", BinaryTagTypes.LIST); - double x = pos.getDouble(0); - double y = pos.getDouble(1); - double z = pos.getDouble(2); - float yRot = rotation.getFloat(0); - float xRot = rotation.getFloat(1); + LinCompoundTag tag = entity.getNbtReference().getValue(); + LinListTag pos = tag.getListTag("Pos", LinTagType.doubleTag()); + LinListTag rotation = tag.getListTag("Rotation", LinTagType.floatTag()); + double x = pos.get(0).value(); + double y = pos.get(1).value(); + double z = pos.get(2).value(); + float yRot = rotation.get(0).value(); + float xRot = rotation.get(1).value(); Location location = new Location(editSession.getWorld(), x, y, z, yRot, xRot); editSession.createEntity(location, entity); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java index 6b8de78fc..6b42ba727 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java @@ -73,7 +73,7 @@ public abstract class ChunkStore implements Closeable { * @return chunk coordinates */ public static BlockVector2 toChunk(BlockVector3 position) { - return BlockVector2.at(position.getX() >> CHUNK_SHIFTS, position.getZ() >> CHUNK_SHIFTS); + return BlockVector2.at(position.x() >> CHUNK_SHIFTS, position.z() >> CHUNK_SHIFTS); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java index 58692732f..c8788a9ce 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.world.storage; -import com.sk89q.jnbt.AdventureNBTConverter; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.Tag; @@ -54,7 +53,7 @@ public class ChunkStoreHelper { public static CompoundTag readCompoundTag(ChunkDataInputSupplier input) throws DataException, IOException { try (InputStream stream = input.openInputStream(); - NBTInputStream nbt = new NBTInputStream(stream)) { + NBTInputStream nbt = new NBTInputStream(stream)) { Tag tag = nbt.readNamedTag().getTag(); if (!(tag instanceof CompoundTag)) { throw new ChunkStoreException("CompoundTag expected for chunk; got " @@ -99,23 +98,20 @@ public class ChunkStoreHelper { if ((dataVersion > 0 || hasLevelSections(rootTag)) && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks final DataFixer dataFixer = platform.getDataFixer(); if (dataFixer != null) { - //FAWE start - CBT - rootTag = (CompoundTag) AdventureNBTConverter.fromAdventure(dataFixer.fixUp(DataFixer.FixTypes.CHUNK, - rootTag.asBinaryTag(), dataVersion)); - //FAWE end + rootTag = new CompoundTag(dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag.toLinTag(), dataVersion)); dataVersion = currentDataVersion; } } if (dataVersion >= Constants.DATA_VERSION_MC_1_18) { - return new AnvilChunk18(rootTag, entitiesTag); + return new AnvilChunk18(rootTag); } - Map children = rootTag.getValue(); + Map> children = rootTag.getValue(); CompoundTag tag = null; // Find Level tag - for (Map.Entry entry : children.entrySet()) { + for (Map.Entry> entry : children.entrySet()) { if (entry.getKey().equals("Level")) { if (entry.getValue() instanceof CompoundTag) { tag = (CompoundTag) entry.getValue(); @@ -150,7 +146,7 @@ public class ChunkStoreHelper { return new AnvilChunk13(tag); } - Map tags = tag.getValue(); + Map> tags = tag.getValue(); if (tags.containsKey("Sections")) { return new AnvilChunk(tag); } @@ -159,8 +155,8 @@ public class ChunkStoreHelper { } private static boolean hasLevelSections(CompoundTag rootTag) { - Map children = rootTag.getValue(); - Tag levelTag = children.get("Level"); + Map> children = rootTag.getValue(); + Tag levelTag = children.get("Level"); if (levelTag instanceof CompoundTag) { return ((CompoundTag) levelTag).getValue().containsKey("Sections"); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java index 5e534765a..0159c3880 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java @@ -44,8 +44,8 @@ public abstract class LegacyChunkStore extends ChunkStore { * @return pathname */ public static String getFilename(BlockVector2 position, String separator) { - int x = position.getBlockX(); - int z = position.getBlockZ(); + int x = position.x(); + int z = position.z(); String folder1 = Integer.toString(divisorMod(x, 64), 36); String folder2 = Integer.toString(divisorMod(z, 64), 36); @@ -68,8 +68,8 @@ public abstract class LegacyChunkStore extends ChunkStore { @Override public CompoundTag getChunkTag(BlockVector2 position, World world) throws DataException, IOException { - int x = position.getBlockX(); - int z = position.getBlockZ(); + int x = position.x(); + int z = position.z(); String folder1 = Integer.toString(divisorMod(x, 64), 36); String folder2 = Integer.toString(divisorMod(z, 64), 36); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionChunkStore.java index 5b43de521..a4e06145e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionChunkStore.java @@ -40,8 +40,8 @@ public abstract class McRegionChunkStore extends ChunkStore { * @return the filename */ public static String getFilename(BlockVector2 position) { - int x = position.getBlockX(); - int z = position.getBlockZ(); + int x = position.x(); + int z = position.z(); return "r." + (x >> 5) + "." + (z >> 5) + ".mca"; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionReader.java index 193f03b06..88e455200 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionReader.java @@ -119,8 +119,8 @@ public class McRegionReader { * @throws DataException if there is an error getting the chunk data */ public synchronized InputStream getChunkInputStream(BlockVector2 position) throws IOException, DataException { - int x = position.getBlockX() & 31; - int z = position.getBlockZ() & 31; + int x = position.x() & 31; + int z = position.z() & 31; int offset = getOffset(x, z); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/NBTConversions.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/NBTConversions.java index 8d82026ff..90d552c10 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/NBTConversions.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/NBTConversions.java @@ -22,6 +22,9 @@ package com.sk89q.worldedit.world.storage; import com.sk89q.jnbt.ListTag; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.util.Location; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; import static com.google.common.base.Preconditions.checkNotNull; @@ -44,15 +47,41 @@ public final class NBTConversions { * @param positionTag the position tag * @param directionTag the direction tag * @return a location + * @deprecated Use {@link #toLocation(Extent, LinListTag, LinListTag)} instead. */ + @Deprecated public static Location toLocation(Extent extent, ListTag positionTag, ListTag directionTag) { checkNotNull(extent); checkNotNull(positionTag); checkNotNull(directionTag); return new Location( - extent, - positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), - directionTag.getFloat(0), directionTag.getFloat(1) + extent, + positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), + directionTag.getFloat(0), directionTag.getFloat(1)); + } + + /** + * Read a {@code Location} from two list tags, the first of which contains + * three numbers for the X, Y, and Z components, and the second of + * which contains two numbers, the yaw and pitch in degrees. + * + *

For values that are unavailable, their values will be 0.

+ * + * @param extent the extent + * @param positionTag the position tag + * @param rotationTag the rotation tag + * @return a location + */ + public static Location toLocation(Extent extent, LinListTag positionTag, LinListTag rotationTag) { + int posTagSize = positionTag.value().size(); + int rotTagSize = rotationTag.value().size(); + return new Location( + extent, + posTagSize > 0 ? positionTag.get(0).valueAsDouble() : 0, + posTagSize > 1 ? positionTag.get(1).valueAsDouble() : 0, + posTagSize > 2 ? positionTag.get(2).valueAsDouble() : 0, + rotTagSize > 0 ? rotationTag.get(0).valueAsFloat() : 0, + rotTagSize > 1 ? rotationTag.get(1).valueAsFloat() : 0 ); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherType.java index ea78ee112..4a7b3cd0c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherType.java @@ -22,43 +22,20 @@ package com.sk89q.worldedit.world.weather; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.Registry; -public class WeatherType implements Keyed { - +public record WeatherType(String id) implements Keyed { public static final Registry REGISTRY = new Registry<>("weather type"); - private final String id; - - public WeatherType(String id) { - this.id = id; - } - - @Override - public String getId() { - return this.id; - } - /** * Gets the name of this weather, or the ID if the name cannot be found. * * @return The name, or ID */ public String getName() { - return getId(); + return id(); } @Override public String toString() { - return getId(); + return id(); } - - @Override - public int hashCode() { - return this.id.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof WeatherType && this.id.equals(((WeatherType) obj).id); - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java index 404e8d6da..458f17f25 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java @@ -35,7 +35,7 @@ public final class WeatherTypes { } public static WeatherType register(WeatherType weather) { - return WeatherType.REGISTRY.register(weather.getId(), weather); + return WeatherType.REGISTRY.register(weather.id(), weather); } @Nullable diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.115.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.115.json deleted file mode 100644 index a08b75364..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.115.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"powerSource":false,"lightValue":0,"hardness":0.7,"resistance":0.7,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:air","localizedName":"Air","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":1200,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Sapling","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":false,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"powerSource":false,"lightValue":15,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"powerSource":false,"lightValue":0,"hardness":2.8,"resistance":2.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.989,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a0a0ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":1.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"powerSource":false,"lightValue":1,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"powerSource":false,"lightValue":1,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":true,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"powerSource":false,"lightValue":0,"hardness":0.4,"resistance":0.4,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"powerSource":false,"lightValue":15,"hardness":2,"resistance":2,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":1200,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"powerSource":false,"lightValue":0,"hardness":0.4,"resistance":0.4,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"powerSource":false,"lightValue":0,"hardness":0.4,"resistance":0.4,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#976d4d","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"powerSource":false,"lightValue":0,"hardness":4,"resistance":4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":3,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"powerSource":true,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"powerSource":false,"lightValue":15,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":1200,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"powerSource":true,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"powerSource":true,"lightValue":0,"hardness":0.7,"resistance":0.7,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#976d4d","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"powerSource":false,"lightValue":1,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7fb238","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":1200,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"powerSource":false,"lightValue":15,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"powerSource":false,"lightValue":15,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"powerSource":false,"lightValue":1,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"powerSource":false,"lightValue":14,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":9,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"powerSource":false,"lightValue":7,"hardness":22.5,"resistance":600,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#976d4d","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"powerSource":false,"lightValue":15,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":true,"fullCube":true,"slipperiness":0.98,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a0a0ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:glass","localizedName":"Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"powerSource":false,"lightValue":15,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:grass","localizedName":"Grass","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7fb238","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:grass_path","localizedName":"Grass Path","material":{"powerSource":false,"lightValue":0,"hardness":0.65,"resistance":0.65,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#976d4d","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7fb238","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":4.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":true,"fullCube":true,"slipperiness":0.98,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a0a0ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0.75,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o'Lantern","material":{"powerSource":false,"lightValue":15,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"powerSource":false,"lightValue":0,"hardness":0.4,"resistance":0.4,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"powerSource":false,"lightValue":15,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lapis_block","localizedName":"Lapis Lazuli Block","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"powerSource":false,"lightValue":15,"hardness":100,"resistance":100,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":true,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#ff0000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"powerSource":true,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:lever","localizedName":"Lever","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:loom","localizedName":"Loom","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"powerSource":false,"lightValue":3,"hardness":0.5,"resistance":0.5,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#707070","isTranslucent":true,"hasContainer":false}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7fb238","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"powerSource":false,"lightValue":11,"hardness":-1,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7fb238","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"powerSource":false,"lightValue":0,"hardness":0.4,"resistance":0.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"powerSource":true,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"powerSource":false,"lightValue":0,"hardness":50,"resistance":1200,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.98,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a0a0ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#976d4d","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"powerSource":false,"lightValue":0,"hardness":0.7,"resistance":0.7,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"powerSource":false,"lightValue":0,"hardness":0.7,"resistance":0.7,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"powerSource":true,"lightValue":0,"hardness":5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"powerSource":true,"lightValue":7,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"powerSource":true,"lightValue":7,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"powerSource":true,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"powerSource":true,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":true,"hasContainer":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"powerSource":false,"lightValue":15,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"powerSource":false,"lightValue":6,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.8,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a4a8b8","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"powerSource":false,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":true,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#ffffff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#ffffff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spawner","localizedName":"Spawner","material":{"powerSource":false,"lightValue":0,"hardness":5,"resistance":5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#e5e533","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"powerSource":false,"lightValue":0,"hardness":3,"resistance":3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":true,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone","localizedName":"Stone","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"powerSource":true,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":6,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"powerSource":false,"lightValue":0,"hardness":3.5,"resistance":3.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"powerSource":false,"lightValue":0,"hardness":-1,"resistance":3600000,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#a7a7a7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#ff0000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"powerSource":false,"lightValue":14,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"powerSource":true,"lightValue":0,"hardness":2.5,"resistance":2.5,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":true}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"powerSource":true,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"powerSource":false,"lightValue":0,"hardness":1.5,"resistance":6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"powerSource":false,"lightValue":14,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:water","localizedName":"Water","material":{"powerSource":false,"lightValue":0,"hardness":100,"resistance":100,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":true,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":true,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#4040ff","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"powerSource":false,"lightValue":0,"hardness":0.6,"resistance":0.6,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#e5e533","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":true,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"powerSource":false,"lightValue":0,"hardness":0,"resistance":0,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#007c00","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"powerSource":false,"lightValue":0,"hardness":0.2,"resistance":0.2,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"powerSource":false,"lightValue":0,"hardness":0.1,"resistance":0.1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":true,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"powerSource":false,"lightValue":0,"hardness":1.8,"resistance":1.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"powerSource":false,"lightValue":0,"hardness":0.5,"resistance":0.5,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#f7e9a3","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.4,"resistance":1.4,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"powerSource":false,"lightValue":0,"hardness":2,"resistance":2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#7f3fb2","isTranslucent":true,"hasContainer":true}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"powerSource":false,"lightValue":0,"hardness":0.3,"resistance":0.3,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"powerSource":false,"lightValue":0,"hardness":1.25,"resistance":4.2,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":false,"opaque":true,"replacedDuringPlacement":false,"toolRequired":true,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#707070","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#8f7748","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"powerSource":false,"lightValue":0,"hardness":0.8,"resistance":0.8,"ticksRandomly":false,"fullCube":true,"slipperiness":0.6,"liquid":false,"solid":true,"movementBlocker":true,"burnable":true,"opaque":true,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":false,"unpushable":false,"mapColor":"#c7c7c7","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"powerSource":false,"lightValue":0,"hardness":1,"resistance":1,"ticksRandomly":false,"fullCube":false,"slipperiness":0.6,"liquid":false,"solid":false,"movementBlocker":false,"burnable":false,"opaque":false,"replacedDuringPlacement":false,"toolRequired":false,"fragileWhenPushed":true,"unpushable":false,"mapColor":"#000000","isTranslucent":false,"hasContainer":false}}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.116.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.116.json deleted file mode 100644 index b15d6c340..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.116.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:air","localizedName":"Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":30,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Shoot","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:basalt","localizedName":"Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blackstone","localizedName":"Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.8,"slipperiness":0.989,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":true,"lightValue":1,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":true,"lightValue":15,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chain","localizedName":"Chain","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":22.5,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":600,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:glass","localizedName":"Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:grass","localizedName":"Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grass_path","localizedName":"Grass Path","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.65,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.65,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o'Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_block","localizedName":"Lapis Lazuli Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100,"hasContainer":false,"lightValue":15,"liquid":true,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lever","localizedName":"Lever","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lodestone","localizedName":"Lodestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:loom","localizedName":"Loom","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":3,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1,"hasContainer":false,"lightValue":11,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":true}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_fungus","localizedName":"Potted Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_roots","localizedName":"Potted Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_fungus","localizedName":"Potted Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_roots","localizedName":"Potted Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.8,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":true,"lightValue":10,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_fire","localizedName":"Soul Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_wall_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spawner","localizedName":"Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:stone","localizedName":"Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:target","localizedName":"Target","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines_plant","localizedName":"Twisting Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_button","localizedName":"Warped Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_door","localizedName":"Warped Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water","localizedName":"Water","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines_plant","localizedName":"Weeping Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}}] \ No newline at end of file diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.117.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.117.json deleted file mode 100644 index 4f60b0771..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.117.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:air","localizedName":"Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":5,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":30.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea","localizedName":"Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Shoot","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:basalt","localizedName":"Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:big_dripleaf_stem","localizedName":"Big Dripleaf Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle","localizedName":"Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle_cake","localizedName":"Cake with Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blackstone","localizedName":"Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle_cake","localizedName":"Cake with Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.8,"slipperiness":0.989,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":true,"lightValue":1,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle_cake","localizedName":"Cake with Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:calcite","localizedName":"Calcite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":15,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle","localizedName":"Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle_cake","localizedName":"Cake with Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines","localizedName":"Cave Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines_plant","localizedName":"Cave Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chain","localizedName":"Chain","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":4.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:copper_block","localizedName":"Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle_cake","localizedName":"Cake with Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate","localizedName":"Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.65,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.65,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":22.5,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":600.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:glass","localizedName":"Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:grass","localizedName":"Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle_cake","localizedName":"Cake with Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle","localizedName":"Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle_cake","localizedName":"Cake with Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":4,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":15,"liquid":true,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava_cauldron","localizedName":"Lava Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lever","localizedName":"Lever","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light","localizedName":"Light","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":3600000.8,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle_cake","localizedName":"Cake with Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle_cake","localizedName":"Cake with Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle_cake","localizedName":"Cake with Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lodestone","localizedName":"Lodestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:loom","localizedName":"Loom","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle_cake","localizedName":"Cake with Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":3,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":2,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_block","localizedName":"Moss Block","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":11,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":true}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle_cake","localizedName":"Cake with Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle_cake","localizedName":"Cake with Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azalea_bush","localizedName":"Potted Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_fungus","localizedName":"Potted Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_roots","localizedName":"Potted Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_flowering_azalea_bush","localizedName":"Potted Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_fungus","localizedName":"Potted Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_roots","localizedName":"Potted Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow","localizedName":"Powder Snow","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow_cauldron","localizedName":"Powder Snow Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle_cake","localizedName":"Cake with Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle","localizedName":"Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle_cake","localizedName":"Cake with Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.8,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":10,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_fire","localizedName":"Soul Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_wall_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spawner","localizedName":"Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:stone","localizedName":"Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:target","localizedName":"Target","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tuff","localizedName":"Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines_plant","localizedName":"Twisting Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_button","localizedName":"Warped Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_door","localizedName":"Warped Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water","localizedName":"Water","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water_cauldron","localizedName":"Water Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines_plant","localizedName":"Weeping Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle","localizedName":"White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle_cake","localizedName":"Cake with White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle_cake","localizedName":"Cake with Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.119.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.119.json deleted file mode 100644 index 688a8c97d..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.119.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:air","localizedName":"Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":5,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":30.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea","localizedName":"Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Shoot","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:basalt","localizedName":"Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:big_dripleaf_stem","localizedName":"Big Dripleaf Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle","localizedName":"Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle_cake","localizedName":"Cake with Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blackstone","localizedName":"Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle_cake","localizedName":"Cake with Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.8,"slipperiness":0.989,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":true,"lightValue":1,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle_cake","localizedName":"Cake with Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:calcite","localizedName":"Calcite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":15,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle","localizedName":"Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle_cake","localizedName":"Cake with Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines","localizedName":"Cave Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines_plant","localizedName":"Cave Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chain","localizedName":"Chain","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":4.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:copper_block","localizedName":"Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle_cake","localizedName":"Cake with Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate","localizedName":"Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.65,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.65,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":22.5,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":600.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:glass","localizedName":"Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:grass","localizedName":"Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle_cake","localizedName":"Cake with Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle","localizedName":"Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle_cake","localizedName":"Cake with Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":4,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":15,"liquid":true,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava_cauldron","localizedName":"Lava Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lever","localizedName":"Lever","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light","localizedName":"Light","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":3600000.8,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle_cake","localizedName":"Cake with Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle_cake","localizedName":"Cake with Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle_cake","localizedName":"Cake with Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lodestone","localizedName":"Lodestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:loom","localizedName":"Loom","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle_cake","localizedName":"Cake with Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":3,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wall_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":2,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_block","localizedName":"Moss Block","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:mud","localizedName":"Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":11,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":true}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle_cake","localizedName":"Cake with Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle_cake","localizedName":"Cake with Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azalea_bush","localizedName":"Potted Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_fungus","localizedName":"Potted Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_roots","localizedName":"Potted Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_flowering_azalea_bush","localizedName":"Potted Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_mangrove_propagule","localizedName":"Potted Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_fungus","localizedName":"Potted Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_roots","localizedName":"Potted Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow","localizedName":"Powder Snow","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow_cauldron","localizedName":"Powder Snow Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle_cake","localizedName":"Cake with Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle","localizedName":"Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle_cake","localizedName":"Cake with Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":55.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk","localizedName":"Sculk","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.8,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":10,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_fire","localizedName":"Soul Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_wall_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spawner","localizedName":"Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:stone","localizedName":"Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:target","localizedName":"Target","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tuff","localizedName":"Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines_plant","localizedName":"Twisting Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_button","localizedName":"Warped Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_door","localizedName":"Warped Door","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water","localizedName":"Water","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water_cauldron","localizedName":"Water Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines_plant","localizedName":"Weeping Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle","localizedName":"White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle_cake","localizedName":"Cake with White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle_cake","localizedName":"Cake with Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.121.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.121.json new file mode 100644 index 000000000..c86ab5e46 --- /dev/null +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.121.json @@ -0,0 +1 @@ +[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_hanging_sign","localizedName":"Acacia Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_hanging_sign","localizedName":"Acacia Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:air","localizedName":"Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":5,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":30.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea","localizedName":"Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_block","localizedName":"Block of Bamboo","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_button","localizedName":"Bamboo Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_door","localizedName":"Bamboo Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_fence","localizedName":"Bamboo Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_fence_gate","localizedName":"Bamboo Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_hanging_sign","localizedName":"Bamboo Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic","localizedName":"Bamboo Mosaic","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic_slab","localizedName":"Bamboo Mosaic Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic_stairs","localizedName":"Bamboo Mosaic Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_planks","localizedName":"Bamboo Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_pressure_plate","localizedName":"Bamboo Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Shoot","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sign","localizedName":"Bamboo Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_slab","localizedName":"Bamboo Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_stairs","localizedName":"Bamboo Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_trapdoor","localizedName":"Bamboo Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_wall_hanging_sign","localizedName":"Bamboo Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_wall_sign","localizedName":"Bamboo Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:basalt","localizedName":"Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:big_dripleaf_stem","localizedName":"Big Dripleaf Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_hanging_sign","localizedName":"Birch Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_hanging_sign","localizedName":"Birch Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle","localizedName":"Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle_cake","localizedName":"Cake with Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#251610","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blackstone","localizedName":"Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle_cake","localizedName":"Cake with Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.8,"slipperiness":0.989,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3e5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":true,"lightValue":1,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle_cake","localizedName":"Cake with Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:calcite","localizedName":"Calcite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:calibrated_sculk_sensor","localizedName":"Calibrated Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":15,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle","localizedName":"Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle_cake","localizedName":"Cake with Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines","localizedName":"Cave Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines_plant","localizedName":"Cave Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chain","localizedName":"Chain","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cherry_button","localizedName":"Cherry Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_door","localizedName":"Cherry Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_fence","localizedName":"Cherry Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_fence_gate","localizedName":"Cherry Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_hanging_sign","localizedName":"Cherry Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_leaves","localizedName":"Cherry Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_log","localizedName":"Cherry Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_planks","localizedName":"Cherry Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_pressure_plate","localizedName":"Cherry Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_sapling","localizedName":"Cherry Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_sign","localizedName":"Cherry Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_slab","localizedName":"Cherry Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_stairs","localizedName":"Cherry Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_trapdoor","localizedName":"Cherry Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wall_hanging_sign","localizedName":"Cherry Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wall_sign","localizedName":"Cherry Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wood","localizedName":"Cherry Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:chiseled_bookshelf","localizedName":"Chiseled Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chiseled_copper","localizedName":"Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_tuff","localizedName":"Chiseled Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_tuff_bricks","localizedName":"Chiseled Tuff Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":4.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:copper_block","localizedName":"Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_bulb","localizedName":"Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_door","localizedName":"Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_grate","localizedName":"Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_trapdoor","localizedName":"Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crafter","localizedName":"Crafter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hanging_sign","localizedName":"Crimson Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5c191d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#bd3031","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_hanging_sign","localizedName":"Crimson Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle_cake","localizedName":"Cake with Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#575c5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_hanging_sign","localizedName":"Dark Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_hanging_sign","localizedName":"Dark Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:decorated_pot","localizedName":"Decorated Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8e3c2e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:deepslate","localizedName":"Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.65,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.65,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#00d93a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":22.5,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":600.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_chiseled_copper","localizedName":"Exposed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_bulb","localizedName":"Exposed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_door","localizedName":"Exposed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_grate","localizedName":"Exposed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_trapdoor","localizedName":"Exposed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:glass","localizedName":"Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fa796","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle_cake","localizedName":"Cake with Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle","localizedName":"Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle_cake","localizedName":"Cake with Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c522a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_core","localizedName":"Heavy Core","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":10.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_hanging_sign","localizedName":"Jungle Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_hanging_sign","localizedName":"Jungle Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4a80ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":4,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":15,"liquid":true,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava_cauldron","localizedName":"Lava Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lever","localizedName":"Lever","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light","localizedName":"Light","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":3600000.8,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle_cake","localizedName":"Cake with Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#706c8a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle_cake","localizedName":"Cake with Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle_cake","localizedName":"Cake with Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#677535","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lodestone","localizedName":"Lodestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:loom","localizedName":"Loom","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle_cake","localizedName":"Cake with Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#95576c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":3,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_hanging_sign","localizedName":"Mangrove Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wall_hanging_sign","localizedName":"Mangrove Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wall_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":2,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_block","localizedName":"Moss Block","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:mud","localizedName":"Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#575c5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":11,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":true}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_hanging_sign","localizedName":"Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_hanging_sign","localizedName":"Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle_cake","localizedName":"Cake with Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#9f5224","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxidized_chiseled_copper","localizedName":"Oxidized Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_bulb","localizedName":"Oxidized Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_door","localizedName":"Oxidized Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_grate","localizedName":"Oxidized Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_trapdoor","localizedName":"Oxidized Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:piglin_head","localizedName":"Piglin Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piglin_wall_head","localizedName":"Piglin Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle_cake","localizedName":"Cake with Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_petals","localizedName":"Pink Petals","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:pitcher_crop","localizedName":"Pitcher Crop","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pitcher_plant","localizedName":"Pitcher Plant","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff","localizedName":"Polished Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_slab","localizedName":"Polished Tuff Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_stairs","localizedName":"Polished Tuff Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_wall","localizedName":"Polished Tuff Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azalea_bush","localizedName":"Potted Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cherry_sapling","localizedName":"Potted Cherry Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_fungus","localizedName":"Potted Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_roots","localizedName":"Potted Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_flowering_azalea_bush","localizedName":"Potted Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_mangrove_propagule","localizedName":"Potted Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_torchflower","localizedName":"Potted Torchflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_fungus","localizedName":"Potted Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_roots","localizedName":"Potted Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow","localizedName":"Powder Snow","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow_cauldron","localizedName":"Powder Snow Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle_cake","localizedName":"Cake with Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7a4958","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7a4958","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d8af93","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle","localizedName":"Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle_cake","localizedName":"Cake with Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8e3c2e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":55.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk","localizedName":"Sculk","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:short_grass","localizedName":"Short Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.8,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sniffer_egg","localizedName":"Sniffer Egg","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":10,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_fire","localizedName":"Soul Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_wall_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spawner","localizedName":"Monster Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_hanging_sign","localizedName":"Spruce Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_hanging_sign","localizedName":"Spruce Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:stone","localizedName":"Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_bamboo_block","localizedName":"Block of Stripped Bamboo","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_cherry_log","localizedName":"Stripped Cherry Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_cherry_wood","localizedName":"Stripped Cherry Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5c191d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#562c3e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:suspicious_gravel","localizedName":"Suspicious Gravel","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:suspicious_sand","localizedName":"Suspicious Sand","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:target","localizedName":"Target","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torchflower","localizedName":"Torchflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torchflower_crop","localizedName":"Torchflower Crop","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trial_spawner","localizedName":"Trial Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":50.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tuff","localizedName":"Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_slab","localizedName":"Tuff Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_stairs","localizedName":"Tuff Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_wall","localizedName":"Tuff Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_bricks","localizedName":"Tuff Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_slab","localizedName":"Tuff Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_stairs","localizedName":"Tuff Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_wall","localizedName":"Tuff Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines_plant","localizedName":"Twisting Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vault","localizedName":"Vault","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":50.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#7fa796","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_button","localizedName":"Warped Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_door","localizedName":"Warped Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hanging_sign","localizedName":"Warped Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#562c3e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_hanging_sign","localizedName":"Warped Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#14b485","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water","localizedName":"Water","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water_cauldron","localizedName":"Water Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_chiseled_copper","localizedName":"Waxed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_bulb","localizedName":"Waxed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_door","localizedName":"Waxed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_grate","localizedName":"Waxed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_trapdoor","localizedName":"Waxed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_chiseled_copper","localizedName":"Waxed Exposed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_bulb","localizedName":"Waxed Exposed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_door","localizedName":"Waxed Exposed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_grate","localizedName":"Waxed Exposed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_trapdoor","localizedName":"Waxed Exposed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_chiseled_copper","localizedName":"Waxed Oxidized Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_bulb","localizedName":"Waxed Oxidized Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_door","localizedName":"Waxed Oxidized Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_grate","localizedName":"Waxed Oxidized Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_trapdoor","localizedName":"Waxed Oxidized Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_chiseled_copper","localizedName":"Waxed Weathered Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_bulb","localizedName":"Waxed Weathered Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_door","localizedName":"Waxed Weathered Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_grate","localizedName":"Waxed Weathered Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_trapdoor","localizedName":"Waxed Weathered Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_chiseled_copper","localizedName":"Weathered Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_bulb","localizedName":"Weathered Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_door","localizedName":"Weathered Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_grate","localizedName":"Weathered Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_trapdoor","localizedName":"Weathered Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines_plant","localizedName":"Weeping Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle","localizedName":"White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle_cake","localizedName":"Cake with White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle_cake","localizedName":"Cake with Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ba8524","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}}] \ No newline at end of file diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.1213.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.1213.json new file mode 100644 index 000000000..c026d82f0 --- /dev/null +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.1213.json @@ -0,0 +1 @@ +[{"id":"minecraft:acacia_button","localizedName":"Acacia Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_hanging_sign","localizedName":"Acacia Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_hanging_sign","localizedName":"Acacia Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wall_sign","localizedName":"Acacia Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:air","localizedName":"Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:allium","localizedName":"Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":5,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":30.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite","localizedName":"Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:anvil","localizedName":"Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:attached_melon_stem","localizedName":"Attached Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:attached_pumpkin_stem","localizedName":"Attached Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea","localizedName":"Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo","localizedName":"Bamboo","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_block","localizedName":"Block of Bamboo","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_button","localizedName":"Bamboo Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_door","localizedName":"Bamboo Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_fence","localizedName":"Bamboo Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_fence_gate","localizedName":"Bamboo Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_hanging_sign","localizedName":"Bamboo Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic","localizedName":"Bamboo Mosaic","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic_slab","localizedName":"Bamboo Mosaic Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_mosaic_stairs","localizedName":"Bamboo Mosaic Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_planks","localizedName":"Bamboo Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_pressure_plate","localizedName":"Bamboo Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sapling","localizedName":"Bamboo Shoot","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_sign","localizedName":"Bamboo Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_slab","localizedName":"Bamboo Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_stairs","localizedName":"Bamboo Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_trapdoor","localizedName":"Bamboo Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_wall_hanging_sign","localizedName":"Bamboo Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bamboo_wall_sign","localizedName":"Bamboo Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrel","localizedName":"Barrel","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:barrier","localizedName":"Barrier","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:basalt","localizedName":"Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:beacon","localizedName":"Beacon","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bedrock","localizedName":"Bedrock","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beehive","localizedName":"Beehive","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:beetroots","localizedName":"Beetroots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bell","localizedName":"Bell","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:big_dripleaf_stem","localizedName":"Big Dripleaf Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_button","localizedName":"Birch Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_door","localizedName":"Birch Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_hanging_sign","localizedName":"Birch Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_log","localizedName":"Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_hanging_sign","localizedName":"Birch Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wall_sign","localizedName":"Birch Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_bed","localizedName":"Black Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle","localizedName":"Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_candle_cake","localizedName":"Cake with Black Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#251610","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:black_wall_banner","localizedName":"Black Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:black_wool","localizedName":"Black Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blackstone","localizedName":"Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_candle_cake","localizedName":"Cake with Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.8,"slipperiness":0.989,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3e5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:blue_wall_banner","localizedName":"Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bone_block","localizedName":"Bone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brain_coral_wall_fan","localizedName":"Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":true,"lightValue":1,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bricks","localizedName":"Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_candle_cake","localizedName":"Cake with Brown Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#664c33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:brown_wall_banner","localizedName":"Brown Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_column","localizedName":"Bubble Column","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:bubble_coral_wall_fan","localizedName":"Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cactus","localizedName":"Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cake","localizedName":"Cake","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:calcite","localizedName":"Calcite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:calibrated_sculk_sensor","localizedName":"Calibrated Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:campfire","localizedName":"Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":15,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle","localizedName":"Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:candle_cake","localizedName":"Cake with Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carrots","localizedName":"Carrots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cauldron","localizedName":"Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cave_air","localizedName":"Cave Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines","localizedName":"Cave Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cave_vines_plant","localizedName":"Cave Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chain","localizedName":"Chain","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cherry_button","localizedName":"Cherry Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_door","localizedName":"Cherry Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_fence","localizedName":"Cherry Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_fence_gate","localizedName":"Cherry Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_hanging_sign","localizedName":"Cherry Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_leaves","localizedName":"Cherry Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_log","localizedName":"Cherry Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_planks","localizedName":"Cherry Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_pressure_plate","localizedName":"Cherry Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_sapling","localizedName":"Cherry Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_sign","localizedName":"Cherry Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_slab","localizedName":"Cherry Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_stairs","localizedName":"Cherry Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_trapdoor","localizedName":"Cherry Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wall_hanging_sign","localizedName":"Cherry Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wall_sign","localizedName":"Cherry Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cherry_wood","localizedName":"Cherry Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chest","localizedName":"Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:chiseled_bookshelf","localizedName":"Chiseled Bookshelf","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chiseled_copper","localizedName":"Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_tuff","localizedName":"Chiseled Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chiseled_tuff_bricks","localizedName":"Chiseled Tuff Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:clay","localizedName":"Clay","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:coal_block","localizedName":"Block of Coal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cobweb","localizedName":"Cobweb","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":4.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cocoa","localizedName":"Cocoa","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:command_block","localizedName":"Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:composter","localizedName":"Composter","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:conduit","localizedName":"Conduit","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:copper_block","localizedName":"Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_bulb","localizedName":"Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_door","localizedName":"Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_grate","localizedName":"Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:copper_trapdoor","localizedName":"Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cornflower","localizedName":"Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crafter","localizedName":"Crafter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creaking_heart","localizedName":"Creaking Heart","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:creeper_wall_head","localizedName":"Creeper Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hanging_sign","localizedName":"Crimson Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5c191d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#bd3031","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_hanging_sign","localizedName":"Crimson Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crimson_wall_sign","localizedName":"Crimson Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_candle_cake","localizedName":"Cake with Cyan Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#575c5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:cyan_wall_banner","localizedName":"Cyan Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:dandelion","localizedName":"Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_hanging_sign","localizedName":"Dark Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_hanging_sign","localizedName":"Dark Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wall_sign","localizedName":"Dark Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_brain_coral_wall_fan","localizedName":"Dead Brain Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bubble_coral_wall_fan","localizedName":"Dead Bubble Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_fire_coral_wall_fan","localizedName":"Dead Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_horn_coral_wall_fan","localizedName":"Dead Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dead_tube_coral_wall_fan","localizedName":"Dead Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:decorated_pot","localizedName":"Decorated Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8e3c2e","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:deepslate","localizedName":"Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":4.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite","localizedName":"Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dirt","localizedName":"Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.65,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.65,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dispenser","localizedName":"Dispenser","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dragon_wall_head","localizedName":"Dragon Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:dropper","localizedName":"Dropper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#00d93a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_gateway","localizedName":"End Gateway","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal","localizedName":"End Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#191919","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_rod","localizedName":"End Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:end_stone","localizedName":"End Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":9.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":22.5,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":600.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_chiseled_copper","localizedName":"Exposed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_bulb","localizedName":"Exposed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_door","localizedName":"Exposed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_grate","localizedName":"Exposed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_copper_trapdoor","localizedName":"Exposed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:farmland","localizedName":"Farmland","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fern","localizedName":"Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire","localizedName":"Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fire_coral_wall_fan","localizedName":"Fire Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:frosted_ice","localizedName":"Frosted Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:furnace","localizedName":"Furnace","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:glass","localizedName":"Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fa796","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:glowstone","localizedName":"Glowstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gold_block","localizedName":"Block of Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite","localizedName":"Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:grass_block","localizedName":"Grass Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gravel","localizedName":"Gravel","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_candle_cake","localizedName":"Cake with Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:gray_wall_banner","localizedName":"Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_bed","localizedName":"Green Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle","localizedName":"Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_candle_cake","localizedName":"Cake with Green Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c522a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:green_wall_banner","localizedName":"Green Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:green_wool","localizedName":"Green Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:grindstone","localizedName":"Grindstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hay_block","localizedName":"Hay Bale","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_core","localizedName":"Heavy Core","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":10.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:honey_block","localizedName":"Honey Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:hopper","localizedName":"Hopper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:horn_coral_wall_fan","localizedName":"Horn Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ice","localizedName":"Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.75,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a4a8b8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.75,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_block","localizedName":"Block of Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_door","localizedName":"Iron Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:jukebox","localizedName":"Jukebox","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_hanging_sign","localizedName":"Jungle Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_hanging_sign","localizedName":"Jungle Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wall_sign","localizedName":"Jungle Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp","localizedName":"Kelp","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:kelp_plant","localizedName":"Kelp Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:ladder","localizedName":"Ladder","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lantern","localizedName":"Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4a80ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":4,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:large_fern","localizedName":"Large Fern","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava","localizedName":"Lava","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":15,"liquid":true,"mapColor":"#ff0000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lava_cauldron","localizedName":"Lava Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lectern","localizedName":"Lectern","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lever","localizedName":"Lever","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light","localizedName":"Light","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":3600000.8,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_candle_cake","localizedName":"Cake with Light Blue Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#706c8a","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_blue_wall_banner","localizedName":"Light Blue Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#6699d8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_candle_cake","localizedName":"Cake with Light Gray Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:light_gray_wall_banner","localizedName":"Light Gray Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lilac","localizedName":"Lilac","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_candle_cake","localizedName":"Cake with Lime Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#677535","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:lime_wall_banner","localizedName":"Lime Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:lodestone","localizedName":"Lodestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":true}},{"id":"minecraft:loom","localizedName":"Loom","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_candle_cake","localizedName":"Cake with Magenta Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#95576c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:magenta_wall_banner","localizedName":"Magenta Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:magma_block","localizedName":"Magma Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":3,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_hanging_sign","localizedName":"Mangrove Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wall_hanging_sign","localizedName":"Mangrove Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wall_sign","localizedName":"Mangrove Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":2,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon","localizedName":"Melon","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fcc19","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:melon_stem","localizedName":"Melon Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_block","localizedName":"Moss Block","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:moving_piston","localizedName":"Moving Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:mud","localizedName":"Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#575c5c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:mycelium","localizedName":"Mycelium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_portal","localizedName":"Nether Portal","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":-1.0,"hasContainer":false,"lightValue":11,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":true}},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:netherrack","localizedName":"Netherrack","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:note_block","localizedName":"Note Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_button","localizedName":"Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_door","localizedName":"Oak Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_hanging_sign","localizedName":"Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_log","localizedName":"Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_hanging_sign","localizedName":"Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wall_sign","localizedName":"Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:observer","localizedName":"Observer","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:obsidian","localizedName":"Obsidian","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_candle_cake","localizedName":"Cake with Orange Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#9f5224","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wall_banner","localizedName":"Orange Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:oxidized_chiseled_copper","localizedName":"Oxidized Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_bulb","localizedName":"Oxidized Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_door","localizedName":"Oxidized Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_grate","localizedName":"Oxidized Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_copper_trapdoor","localizedName":"Oxidized Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a0a0ff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.98,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_hanging_moss","localizedName":"Pale Hanging Moss","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_moss_block","localizedName":"Pale Moss Block","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_moss_carpet","localizedName":"Pale Moss Carpet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_button","localizedName":"Pale Oak Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_door","localizedName":"Pale Oak Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_fence","localizedName":"Pale Oak Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_fence_gate","localizedName":"Pale Oak Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_hanging_sign","localizedName":"Pale Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_leaves","localizedName":"Pale Oak Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c522a","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_log","localizedName":"Pale Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_planks","localizedName":"Pale Oak Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_pressure_plate","localizedName":"Pale Oak Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_sapling","localizedName":"Pale Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_sign","localizedName":"Pale Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_slab","localizedName":"Pale Oak Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_stairs","localizedName":"Pale Oak Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_trapdoor","localizedName":"Pale Oak Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_wall_hanging_sign","localizedName":"Pale Oak Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_wall_sign","localizedName":"Pale Oak Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pale_oak_wood","localizedName":"Pale Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:peony","localizedName":"Peony","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:piglin_head","localizedName":"Piglin Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piglin_wall_head","localizedName":"Piglin Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_candle_cake","localizedName":"Cake with Pink Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_petals","localizedName":"Pink Petals","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wall_banner","localizedName":"Pink Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f27fa5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:piston","localizedName":"Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:piston_head","localizedName":"Piston Head","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:pitcher_crop","localizedName":"Pitcher Crop","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pitcher_plant","localizedName":"Pitcher Plant","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:player_wall_head","localizedName":"Player Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:podzol","localizedName":"Podzol","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c3223","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff","localizedName":"Polished Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_slab","localizedName":"Polished Tuff Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_stairs","localizedName":"Polished Tuff Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:polished_tuff_wall","localizedName":"Polished Tuff Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:poppy","localizedName":"Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potatoes","localizedName":"Potatoes","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_acacia_sapling","localizedName":"Potted Acacia Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_allium","localizedName":"Potted Allium","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azalea_bush","localizedName":"Potted Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_azure_bluet","localizedName":"Potted Azure Bluet","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_bamboo","localizedName":"Potted Bamboo","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_birch_sapling","localizedName":"Potted Birch Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_blue_orchid","localizedName":"Potted Blue Orchid","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_brown_mushroom","localizedName":"Potted Brown Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cactus","localizedName":"Potted Cactus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cherry_sapling","localizedName":"Potted Cherry Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_cornflower","localizedName":"Potted Cornflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_fungus","localizedName":"Potted Crimson Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_crimson_roots","localizedName":"Potted Crimson Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dandelion","localizedName":"Potted Dandelion","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dark_oak_sapling","localizedName":"Potted Dark Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_dead_bush","localizedName":"Potted Dead Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_fern","localizedName":"Potted Fern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_flowering_azalea_bush","localizedName":"Potted Flowering Azalea","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_jungle_sapling","localizedName":"Potted Jungle Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_lily_of_the_valley","localizedName":"Potted Lily of the Valley","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_mangrove_propagule","localizedName":"Potted Mangrove Propagule","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oak_sapling","localizedName":"Potted Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_orange_tulip","localizedName":"Potted Orange Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_oxeye_daisy","localizedName":"Potted Oxeye Daisy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pale_oak_sapling","localizedName":"Potted Pale Oak Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_pink_tulip","localizedName":"Potted Pink Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_poppy","localizedName":"Potted Poppy","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_mushroom","localizedName":"Potted Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_red_tulip","localizedName":"Potted Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_spruce_sapling","localizedName":"Potted Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_torchflower","localizedName":"Potted Torchflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_fungus","localizedName":"Potted Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_warped_roots","localizedName":"Potted Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_white_tulip","localizedName":"Potted White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:potted_wither_rose","localizedName":"Potted Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow","localizedName":"Powder Snow","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:powder_snow_cauldron","localizedName":"Powder Snow Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:prismarine","localizedName":"Prismarine","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5cdbd5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:pumpkin_stem","localizedName":"Pumpkin Stem","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_candle_cake","localizedName":"Cake with Purple Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7a4958","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7a4958","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purple_wall_banner","localizedName":"Purple Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#b24cd8","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rail","localizedName":"Rail","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.7,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.7,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#faee4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d8af93","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_bed","localizedName":"Red Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle","localizedName":"Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_candle_cake","localizedName":"Cake with Red Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sand","localizedName":"Red Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8e3c2e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wall_banner","localizedName":"Red Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:red_wool","localizedName":"Red Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#9f5224","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wall_torch","localizedName":"Redstone Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":7,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:redstone_wire","localizedName":"Redstone Wire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":55.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#646464","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1200.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sand","localizedName":"Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sandstone","localizedName":"Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk","localizedName":"Sculk","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#4c7f99","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#667f33","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:seagrass","localizedName":"Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:short_grass","localizedName":"Short Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:skeleton_wall_skull","localizedName":"Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:slime_block","localizedName":"Slime Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#7fb238","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.8,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":1,"liquid":false,"mapColor":"#7f3fb2","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:smoker","localizedName":"Smoker","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#191919","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sniffer_egg","localizedName":"Sniffer Egg","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:snow","localizedName":"Snow","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:snow_block","localizedName":"Snow Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":true,"lightValue":10,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_fire","localizedName":"Soul Fire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#6699d8","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#a7a7a7","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:soul_wall_torch","localizedName":"Soul Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":10,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spawner","localizedName":"Monster Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":5.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":5.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:sponge","localizedName":"Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_hanging_sign","localizedName":"Spruce Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":true,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_hanging_sign","localizedName":"Spruce Hanging Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wall_sign","localizedName":"Spruce Sign","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":true}},{"id":"minecraft:stone","localizedName":"Stone","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_button","localizedName":"Stone Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_bamboo_block","localizedName":"Block of Stripped Bamboo","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_cherry_log","localizedName":"Stripped Cherry Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_cherry_wood","localizedName":"Stripped Cherry Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#a04d4e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#5c191d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#943f61","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#664c33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#976d4d","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#993333","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_pale_oak_log","localizedName":"Stripped Pale Oak Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_pale_oak_wood","localizedName":"Stripped Pale Oak Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#815631","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#562c3e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:structure_block","localizedName":"Structure Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":-1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#999999","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3600000.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:structure_void","localizedName":"Structure Void","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sunflower","localizedName":"Sunflower","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:suspicious_gravel","localizedName":"Suspicious Gravel","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:suspicious_sand","localizedName":"Suspicious Sand","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":0.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.25,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:sweet_berry_bush","localizedName":"Sweet Berry Bush","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tall_seagrass","localizedName":"Tall Seagrass","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:target","localizedName":"Target","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#fffcf5","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:terracotta","localizedName":"Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c4c4c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tnt","localizedName":"TNT","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ff0000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torchflower","localizedName":"Torchflower","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:torchflower_crop","localizedName":"Torchflower Crop","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":2.5,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":true,"powerSource":true,"replacedDuringPlacement":false,"resistance":2.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:trial_spawner","localizedName":"Trial Spawner","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":50.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire","localizedName":"Tripwire","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tube_coral_wall_fan","localizedName":"Tube Coral Wall Fan","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#334cb2","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:tuff","localizedName":"Tuff","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_slab","localizedName":"Tuff Brick Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_stairs","localizedName":"Tuff Brick Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_brick_wall","localizedName":"Tuff Brick Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_bricks","localizedName":"Tuff Bricks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_slab","localizedName":"Tuff Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_stairs","localizedName":"Tuff Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:tuff_wall","localizedName":"Tuff Wall","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#392923","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#f7e9a3","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:twisting_vines_plant","localizedName":"Twisting Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vault","localizedName":"Vault","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":50.0,"hasContainer":false,"lightValue":6,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":50.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":15,"liquid":false,"mapColor":"#7fa796","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:vine","localizedName":"Vines","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.2,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:void_air","localizedName":"Void Air","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wall_torch","localizedName":"Torch","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":14,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_button","localizedName":"Warped Button","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_door","localizedName":"Warped Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hanging_sign","localizedName":"Warped Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#562c3e","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.4,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":true,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#4c7f99","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":3.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_hanging_sign","localizedName":"Warped Hanging Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wall_sign","localizedName":"Warped Sign","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#14b485","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water","localizedName":"Water","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":100.0,"hasContainer":false,"lightValue":0,"liquid":true,"mapColor":"#4040ff","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":true,"resistance":100.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:water_cauldron","localizedName":"Water Cauldron","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":2.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#707070","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_chiseled_copper","localizedName":"Waxed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_bulb","localizedName":"Waxed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_door","localizedName":"Waxed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_grate","localizedName":"Waxed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_copper_trapdoor","localizedName":"Waxed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d87f33","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_chiseled_copper","localizedName":"Waxed Exposed Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_bulb","localizedName":"Waxed Exposed Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_door","localizedName":"Waxed Exposed Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_grate","localizedName":"Waxed Exposed Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_copper_trapdoor","localizedName":"Waxed Exposed Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#876b62","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_chiseled_copper","localizedName":"Waxed Oxidized Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_bulb","localizedName":"Waxed Oxidized Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_door","localizedName":"Waxed Oxidized Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_grate","localizedName":"Waxed Oxidized Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_copper_trapdoor","localizedName":"Waxed Oxidized Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#167e86","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_chiseled_copper","localizedName":"Waxed Weathered Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_bulb","localizedName":"Waxed Weathered Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_door","localizedName":"Waxed Weathered Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_grate","localizedName":"Waxed Weathered Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_copper_trapdoor","localizedName":"Waxed Weathered Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_chiseled_copper","localizedName":"Weathered Chiseled Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_bulb","localizedName":"Weathered Copper Bulb","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_door","localizedName":"Weathered Copper Door","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_grate","localizedName":"Weathered Copper Grate","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_copper_trapdoor","localizedName":"Weathered Copper Trapdoor","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":3.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#3a8e8c","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":6.0,"slipperiness":0.6,"solid":true,"ticksRandomly":true,"toolRequired":true,"unpushable":false}},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:weeping_vines_plant","localizedName":"Weeping Vines Plant","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#700200","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.6,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.6,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wheat","localizedName":"Wheat Crops","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":true,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_bed","localizedName":"White Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle","localizedName":"White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#c7c7c7","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_candle_cake","localizedName":"Cake with White Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_carpet","localizedName":"White Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_concrete","localizedName":"White Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#d1b1a1","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:white_tulip","localizedName":"White Tulip","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wall_banner","localizedName":"White Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:white_wool","localizedName":"White Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ffffff","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#007c00","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:wither_skeleton_wall_skull","localizedName":"Wither Skeleton Skull","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","material":{"burnable":true,"fragileWhenPushed":true,"fullCube":false,"hardness":0.2,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_candle_cake","localizedName":"Cake with Yellow Candle","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":0.1,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.1,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.5,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.5,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.4,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.4,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":true,"hardness":2.0,"hasContainer":true,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":2.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":false,"hardness":0.3,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.3,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","material":{"burnable":false,"fragileWhenPushed":false,"fullCube":true,"hardness":1.25,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#ba8524","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":4.2,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":true,"unpushable":false}},{"id":"minecraft:yellow_wall_banner","localizedName":"Yellow Banner","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#8f7748","movementBlocker":true,"opaque":false,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","material":{"burnable":true,"fragileWhenPushed":false,"fullCube":true,"hardness":0.8,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#e5e533","movementBlocker":true,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":0.8,"slipperiness":0.6,"solid":true,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}},{"id":"minecraft:zombie_wall_head","localizedName":"Zombie Head","material":{"burnable":false,"fragileWhenPushed":true,"fullCube":false,"hardness":1.0,"hasContainer":false,"lightValue":0,"liquid":false,"mapColor":"#000000","movementBlocker":false,"opaque":true,"powerSource":false,"replacedDuringPlacement":false,"resistance":1.0,"slipperiness":0.6,"solid":false,"ticksRandomly":false,"toolRequired":false,"unpushable":false}}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.115.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.115.json deleted file mode 100644 index 77b94c077..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.115.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_boat","unlocalizedName":"item.minecraft.acacia_boat","localizedName":"Acacia Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:acacia_button","unlocalizedName":"block.minecraft.acacia_button","localizedName":"Acacia Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_door","unlocalizedName":"block.minecraft.acacia_door","localizedName":"Acacia Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_fence","unlocalizedName":"block.minecraft.acacia_fence","localizedName":"Acacia Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_fence_gate","unlocalizedName":"block.minecraft.acacia_fence_gate","localizedName":"Acacia Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_leaves","unlocalizedName":"block.minecraft.acacia_leaves","localizedName":"Acacia Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_log","unlocalizedName":"block.minecraft.acacia_log","localizedName":"Acacia Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_planks","unlocalizedName":"block.minecraft.acacia_planks","localizedName":"Acacia Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_pressure_plate","unlocalizedName":"block.minecraft.acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_sapling","unlocalizedName":"block.minecraft.acacia_sapling","localizedName":"Acacia Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_sign","unlocalizedName":"block.minecraft.acacia_sign","localizedName":"Acacia Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:acacia_slab","unlocalizedName":"block.minecraft.acacia_slab","localizedName":"Acacia Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_stairs","unlocalizedName":"block.minecraft.acacia_stairs","localizedName":"Acacia Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_trapdoor","unlocalizedName":"block.minecraft.acacia_trapdoor","localizedName":"Acacia Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:acacia_wood","unlocalizedName":"block.minecraft.acacia_wood","localizedName":"Acacia Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:activator_rail","unlocalizedName":"block.minecraft.activator_rail","localizedName":"Activator Rail","maxDamage":0,"maxStackSize":64},{"id":"minecraft:air","unlocalizedName":"block.minecraft.air","localizedName":"Air","maxDamage":0,"maxStackSize":64},{"id":"minecraft:allium","unlocalizedName":"block.minecraft.allium","localizedName":"Allium","maxDamage":0,"maxStackSize":64},{"id":"minecraft:andesite","unlocalizedName":"block.minecraft.andesite","localizedName":"Andesite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:andesite_slab","unlocalizedName":"block.minecraft.andesite_slab","localizedName":"Andesite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:andesite_stairs","unlocalizedName":"block.minecraft.andesite_stairs","localizedName":"Andesite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:andesite_wall","unlocalizedName":"block.minecraft.andesite_wall","localizedName":"Andesite Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:anvil","unlocalizedName":"block.minecraft.anvil","localizedName":"Anvil","maxDamage":0,"maxStackSize":64},{"id":"minecraft:apple","unlocalizedName":"item.minecraft.apple","localizedName":"Apple","maxDamage":0,"maxStackSize":64},{"id":"minecraft:armor_stand","unlocalizedName":"item.minecraft.armor_stand","localizedName":"Armor Stand","maxDamage":0,"maxStackSize":16},{"id":"minecraft:arrow","unlocalizedName":"item.minecraft.arrow","localizedName":"Arrow","maxDamage":0,"maxStackSize":64},{"id":"minecraft:azure_bluet","unlocalizedName":"block.minecraft.azure_bluet","localizedName":"Azure Bluet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:baked_potato","unlocalizedName":"item.minecraft.baked_potato","localizedName":"Baked Potato","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bamboo","unlocalizedName":"block.minecraft.bamboo","localizedName":"Bamboo","maxDamage":0,"maxStackSize":64},{"id":"minecraft:barrel","unlocalizedName":"block.minecraft.barrel","localizedName":"Barrel","maxDamage":0,"maxStackSize":64},{"id":"minecraft:barrier","unlocalizedName":"block.minecraft.barrier","localizedName":"Barrier","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bat_spawn_egg","unlocalizedName":"item.minecraft.bat_spawn_egg","localizedName":"Bat Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beacon","unlocalizedName":"block.minecraft.beacon","localizedName":"Beacon","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bedrock","unlocalizedName":"block.minecraft.bedrock","localizedName":"Bedrock","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bee_nest","unlocalizedName":"block.minecraft.bee_nest","localizedName":"Bee Nest","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bee_spawn_egg","unlocalizedName":"item.minecraft.bee_spawn_egg","localizedName":"Bee Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beef","unlocalizedName":"item.minecraft.beef","localizedName":"Raw Beef","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beehive","unlocalizedName":"block.minecraft.beehive","localizedName":"Beehive","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beetroot","unlocalizedName":"item.minecraft.beetroot","localizedName":"Beetroot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beetroot_seeds","unlocalizedName":"item.minecraft.beetroot_seeds","localizedName":"Beetroot Seeds","maxDamage":0,"maxStackSize":64},{"id":"minecraft:beetroot_soup","unlocalizedName":"item.minecraft.beetroot_soup","localizedName":"Beetroot Soup","maxDamage":0,"maxStackSize":1},{"id":"minecraft:bell","unlocalizedName":"block.minecraft.bell","localizedName":"Bell","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_boat","unlocalizedName":"item.minecraft.birch_boat","localizedName":"Birch Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:birch_button","unlocalizedName":"block.minecraft.birch_button","localizedName":"Birch Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_door","unlocalizedName":"block.minecraft.birch_door","localizedName":"Birch Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_fence","unlocalizedName":"block.minecraft.birch_fence","localizedName":"Birch Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_fence_gate","unlocalizedName":"block.minecraft.birch_fence_gate","localizedName":"Birch Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_leaves","unlocalizedName":"block.minecraft.birch_leaves","localizedName":"Birch Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_log","unlocalizedName":"block.minecraft.birch_log","localizedName":"Birch Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_planks","unlocalizedName":"block.minecraft.birch_planks","localizedName":"Birch Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_pressure_plate","unlocalizedName":"block.minecraft.birch_pressure_plate","localizedName":"Birch Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_sapling","unlocalizedName":"block.minecraft.birch_sapling","localizedName":"Birch Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_sign","unlocalizedName":"block.minecraft.birch_sign","localizedName":"Birch Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:birch_slab","unlocalizedName":"block.minecraft.birch_slab","localizedName":"Birch Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_stairs","unlocalizedName":"block.minecraft.birch_stairs","localizedName":"Birch Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_trapdoor","unlocalizedName":"block.minecraft.birch_trapdoor","localizedName":"Birch Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:birch_wood","unlocalizedName":"block.minecraft.birch_wood","localizedName":"Birch Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_banner","unlocalizedName":"block.minecraft.black_banner","localizedName":"Black Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:black_bed","unlocalizedName":"block.minecraft.black_bed","localizedName":"Black Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:black_carpet","unlocalizedName":"block.minecraft.black_carpet","localizedName":"Black Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_concrete","unlocalizedName":"block.minecraft.black_concrete","localizedName":"Black Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_concrete_powder","unlocalizedName":"block.minecraft.black_concrete_powder","localizedName":"Black Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_dye","unlocalizedName":"item.minecraft.black_dye","localizedName":"Black Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_glazed_terracotta","unlocalizedName":"block.minecraft.black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_shulker_box","unlocalizedName":"block.minecraft.black_shulker_box","localizedName":"Black Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:black_stained_glass","unlocalizedName":"block.minecraft.black_stained_glass","localizedName":"Black Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_stained_glass_pane","unlocalizedName":"block.minecraft.black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_terracotta","unlocalizedName":"block.minecraft.black_terracotta","localizedName":"Black Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:black_wool","unlocalizedName":"block.minecraft.black_wool","localizedName":"Black Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blast_furnace","unlocalizedName":"block.minecraft.blast_furnace","localizedName":"Blast Furnace","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blaze_powder","unlocalizedName":"item.minecraft.blaze_powder","localizedName":"Blaze Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blaze_rod","unlocalizedName":"item.minecraft.blaze_rod","localizedName":"Blaze Rod","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blaze_spawn_egg","unlocalizedName":"item.minecraft.blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_banner","unlocalizedName":"block.minecraft.blue_banner","localizedName":"Blue Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:blue_bed","unlocalizedName":"block.minecraft.blue_bed","localizedName":"Blue Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:blue_carpet","unlocalizedName":"block.minecraft.blue_carpet","localizedName":"Blue Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_concrete","unlocalizedName":"block.minecraft.blue_concrete","localizedName":"Blue Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_concrete_powder","unlocalizedName":"block.minecraft.blue_concrete_powder","localizedName":"Blue Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_dye","unlocalizedName":"item.minecraft.blue_dye","localizedName":"Blue Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_glazed_terracotta","unlocalizedName":"block.minecraft.blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_ice","unlocalizedName":"block.minecraft.blue_ice","localizedName":"Blue Ice","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_orchid","unlocalizedName":"block.minecraft.blue_orchid","localizedName":"Blue Orchid","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_shulker_box","unlocalizedName":"block.minecraft.blue_shulker_box","localizedName":"Blue Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:blue_stained_glass","unlocalizedName":"block.minecraft.blue_stained_glass","localizedName":"Blue Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_stained_glass_pane","unlocalizedName":"block.minecraft.blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_terracotta","unlocalizedName":"block.minecraft.blue_terracotta","localizedName":"Blue Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:blue_wool","unlocalizedName":"block.minecraft.blue_wool","localizedName":"Blue Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bone","unlocalizedName":"item.minecraft.bone","localizedName":"Bone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bone_block","unlocalizedName":"block.minecraft.bone_block","localizedName":"Bone Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bone_meal","unlocalizedName":"item.minecraft.bone_meal","localizedName":"Bone Meal","maxDamage":0,"maxStackSize":64},{"id":"minecraft:book","unlocalizedName":"item.minecraft.book","localizedName":"Book","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bookshelf","unlocalizedName":"block.minecraft.bookshelf","localizedName":"Bookshelf","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bow","unlocalizedName":"item.minecraft.bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1},{"id":"minecraft:bowl","unlocalizedName":"item.minecraft.bowl","localizedName":"Bowl","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brain_coral","unlocalizedName":"block.minecraft.brain_coral","localizedName":"Brain Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brain_coral_block","unlocalizedName":"block.minecraft.brain_coral_block","localizedName":"Brain Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brain_coral_fan","unlocalizedName":"block.minecraft.brain_coral_fan","localizedName":"Brain Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bread","unlocalizedName":"item.minecraft.bread","localizedName":"Bread","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brewing_stand","unlocalizedName":"block.minecraft.brewing_stand","localizedName":"Brewing Stand","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brick","unlocalizedName":"item.minecraft.brick","localizedName":"Brick","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brick_slab","unlocalizedName":"block.minecraft.brick_slab","localizedName":"Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brick_stairs","unlocalizedName":"block.minecraft.brick_stairs","localizedName":"Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brick_wall","unlocalizedName":"block.minecraft.brick_wall","localizedName":"Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bricks","unlocalizedName":"block.minecraft.bricks","localizedName":"Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_banner","unlocalizedName":"block.minecraft.brown_banner","localizedName":"Brown Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:brown_bed","unlocalizedName":"block.minecraft.brown_bed","localizedName":"Brown Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:brown_carpet","unlocalizedName":"block.minecraft.brown_carpet","localizedName":"Brown Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_concrete","unlocalizedName":"block.minecraft.brown_concrete","localizedName":"Brown Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_concrete_powder","unlocalizedName":"block.minecraft.brown_concrete_powder","localizedName":"Brown Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_dye","unlocalizedName":"item.minecraft.brown_dye","localizedName":"Brown Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_glazed_terracotta","unlocalizedName":"block.minecraft.brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_mushroom","unlocalizedName":"block.minecraft.brown_mushroom","localizedName":"Brown Mushroom","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_mushroom_block","unlocalizedName":"block.minecraft.brown_mushroom_block","localizedName":"Brown Mushroom Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_shulker_box","unlocalizedName":"block.minecraft.brown_shulker_box","localizedName":"Brown Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:brown_stained_glass","unlocalizedName":"block.minecraft.brown_stained_glass","localizedName":"Brown Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_stained_glass_pane","unlocalizedName":"block.minecraft.brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_terracotta","unlocalizedName":"block.minecraft.brown_terracotta","localizedName":"Brown Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:brown_wool","unlocalizedName":"block.minecraft.brown_wool","localizedName":"Brown Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bubble_coral","unlocalizedName":"block.minecraft.bubble_coral","localizedName":"Bubble Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bubble_coral_block","unlocalizedName":"block.minecraft.bubble_coral_block","localizedName":"Bubble Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bubble_coral_fan","unlocalizedName":"block.minecraft.bubble_coral_fan","localizedName":"Bubble Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:bucket","unlocalizedName":"item.minecraft.bucket","localizedName":"Bucket","maxDamage":0,"maxStackSize":16},{"id":"minecraft:cactus","unlocalizedName":"block.minecraft.cactus","localizedName":"Cactus","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cake","unlocalizedName":"block.minecraft.cake","localizedName":"Cake","maxDamage":0,"maxStackSize":1},{"id":"minecraft:campfire","unlocalizedName":"block.minecraft.campfire","localizedName":"Campfire","maxDamage":0,"maxStackSize":64},{"id":"minecraft:carrot","unlocalizedName":"item.minecraft.carrot","localizedName":"Carrot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:carrot_on_a_stick","unlocalizedName":"item.minecraft.carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1},{"id":"minecraft:cartography_table","unlocalizedName":"block.minecraft.cartography_table","localizedName":"Cartography Table","maxDamage":0,"maxStackSize":64},{"id":"minecraft:carved_pumpkin","unlocalizedName":"block.minecraft.carved_pumpkin","localizedName":"Carved Pumpkin","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cat_spawn_egg","unlocalizedName":"item.minecraft.cat_spawn_egg","localizedName":"Cat Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cauldron","unlocalizedName":"block.minecraft.cauldron","localizedName":"Cauldron","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cave_spider_spawn_egg","unlocalizedName":"item.minecraft.cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chain_command_block","unlocalizedName":"block.minecraft.chain_command_block","localizedName":"Chain Command Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chainmail_boots","unlocalizedName":"item.minecraft.chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1},{"id":"minecraft:chainmail_chestplate","unlocalizedName":"item.minecraft.chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1},{"id":"minecraft:chainmail_helmet","unlocalizedName":"item.minecraft.chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1},{"id":"minecraft:chainmail_leggings","unlocalizedName":"item.minecraft.chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1},{"id":"minecraft:charcoal","unlocalizedName":"item.minecraft.charcoal","localizedName":"Charcoal","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chest","unlocalizedName":"block.minecraft.chest","localizedName":"Chest","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chest_minecart","unlocalizedName":"item.minecraft.chest_minecart","localizedName":"Minecart with Chest","maxDamage":0,"maxStackSize":1},{"id":"minecraft:chicken","unlocalizedName":"item.minecraft.chicken","localizedName":"Raw Chicken","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chicken_spawn_egg","unlocalizedName":"item.minecraft.chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chipped_anvil","unlocalizedName":"block.minecraft.chipped_anvil","localizedName":"Chipped Anvil","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chiseled_quartz_block","unlocalizedName":"block.minecraft.chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chiseled_red_sandstone","unlocalizedName":"block.minecraft.chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chiseled_sandstone","unlocalizedName":"block.minecraft.chiseled_sandstone","localizedName":"Chiseled Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chiseled_stone_bricks","unlocalizedName":"block.minecraft.chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chorus_flower","unlocalizedName":"block.minecraft.chorus_flower","localizedName":"Chorus Flower","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chorus_fruit","unlocalizedName":"item.minecraft.chorus_fruit","localizedName":"Chorus Fruit","maxDamage":0,"maxStackSize":64},{"id":"minecraft:chorus_plant","unlocalizedName":"block.minecraft.chorus_plant","localizedName":"Chorus Plant","maxDamage":0,"maxStackSize":64},{"id":"minecraft:clay","unlocalizedName":"block.minecraft.clay","localizedName":"Clay","maxDamage":0,"maxStackSize":64},{"id":"minecraft:clay_ball","unlocalizedName":"item.minecraft.clay_ball","localizedName":"Clay","maxDamage":0,"maxStackSize":64},{"id":"minecraft:clock","unlocalizedName":"item.minecraft.clock","localizedName":"Clock","maxDamage":0,"maxStackSize":64},{"id":"minecraft:coal","unlocalizedName":"item.minecraft.coal","localizedName":"Coal","maxDamage":0,"maxStackSize":64},{"id":"minecraft:coal_block","unlocalizedName":"block.minecraft.coal_block","localizedName":"Block of Coal","maxDamage":0,"maxStackSize":64},{"id":"minecraft:coal_ore","unlocalizedName":"block.minecraft.coal_ore","localizedName":"Coal Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:coarse_dirt","unlocalizedName":"block.minecraft.coarse_dirt","localizedName":"Coarse Dirt","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cobblestone","unlocalizedName":"block.minecraft.cobblestone","localizedName":"Cobblestone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cobblestone_slab","unlocalizedName":"block.minecraft.cobblestone_slab","localizedName":"Cobblestone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cobblestone_stairs","unlocalizedName":"block.minecraft.cobblestone_stairs","localizedName":"Cobblestone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cobblestone_wall","unlocalizedName":"block.minecraft.cobblestone_wall","localizedName":"Cobblestone Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cobweb","unlocalizedName":"block.minecraft.cobweb","localizedName":"Cobweb","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cocoa_beans","unlocalizedName":"item.minecraft.cocoa_beans","localizedName":"Cocoa Beans","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cod","unlocalizedName":"item.minecraft.cod","localizedName":"Raw Cod","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cod_bucket","unlocalizedName":"item.minecraft.cod_bucket","localizedName":"Bucket of Cod","maxDamage":0,"maxStackSize":1},{"id":"minecraft:cod_spawn_egg","unlocalizedName":"item.minecraft.cod_spawn_egg","localizedName":"Cod Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:command_block","unlocalizedName":"block.minecraft.command_block","localizedName":"Command Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:command_block_minecart","unlocalizedName":"item.minecraft.command_block_minecart","localizedName":"Minecart with Command Block","maxDamage":0,"maxStackSize":1},{"id":"minecraft:comparator","unlocalizedName":"block.minecraft.comparator","localizedName":"Redstone Comparator","maxDamage":0,"maxStackSize":64},{"id":"minecraft:compass","unlocalizedName":"item.minecraft.compass","localizedName":"Compass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:composter","unlocalizedName":"block.minecraft.composter","localizedName":"Composter","maxDamage":0,"maxStackSize":64},{"id":"minecraft:conduit","unlocalizedName":"block.minecraft.conduit","localizedName":"Conduit","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_beef","unlocalizedName":"item.minecraft.cooked_beef","localizedName":"Steak","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_chicken","unlocalizedName":"item.minecraft.cooked_chicken","localizedName":"Cooked Chicken","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_cod","unlocalizedName":"item.minecraft.cooked_cod","localizedName":"Cooked Cod","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_mutton","unlocalizedName":"item.minecraft.cooked_mutton","localizedName":"Cooked Mutton","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_porkchop","unlocalizedName":"item.minecraft.cooked_porkchop","localizedName":"Cooked Porkchop","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_rabbit","unlocalizedName":"item.minecraft.cooked_rabbit","localizedName":"Cooked Rabbit","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cooked_salmon","unlocalizedName":"item.minecraft.cooked_salmon","localizedName":"Cooked Salmon","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cookie","unlocalizedName":"item.minecraft.cookie","localizedName":"Cookie","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cornflower","unlocalizedName":"block.minecraft.cornflower","localizedName":"Cornflower","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cow_spawn_egg","unlocalizedName":"item.minecraft.cow_spawn_egg","localizedName":"Cow Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cracked_stone_bricks","unlocalizedName":"block.minecraft.cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:crafting_table","unlocalizedName":"block.minecraft.crafting_table","localizedName":"Crafting Table","maxDamage":0,"maxStackSize":64},{"id":"minecraft:creeper_banner_pattern","unlocalizedName":"item.minecraft.creeper_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1},{"id":"minecraft:creeper_head","unlocalizedName":"block.minecraft.creeper_head","localizedName":"Creeper Head","maxDamage":0,"maxStackSize":64},{"id":"minecraft:creeper_spawn_egg","unlocalizedName":"item.minecraft.creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:crossbow","unlocalizedName":"item.minecraft.crossbow","localizedName":"Crossbow","maxDamage":326,"maxStackSize":1},{"id":"minecraft:cut_red_sandstone","unlocalizedName":"block.minecraft.cut_red_sandstone","localizedName":"Cut Red Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cut_red_sandstone_slab","unlocalizedName":"block.minecraft.cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cut_sandstone","unlocalizedName":"block.minecraft.cut_sandstone","localizedName":"Cut Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cut_sandstone_slab","unlocalizedName":"block.minecraft.cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_banner","unlocalizedName":"block.minecraft.cyan_banner","localizedName":"Cyan Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:cyan_bed","unlocalizedName":"block.minecraft.cyan_bed","localizedName":"Cyan Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:cyan_carpet","unlocalizedName":"block.minecraft.cyan_carpet","localizedName":"Cyan Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_concrete","unlocalizedName":"block.minecraft.cyan_concrete","localizedName":"Cyan Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_concrete_powder","unlocalizedName":"block.minecraft.cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_dye","unlocalizedName":"item.minecraft.cyan_dye","localizedName":"Cyan Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_glazed_terracotta","unlocalizedName":"block.minecraft.cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_shulker_box","unlocalizedName":"block.minecraft.cyan_shulker_box","localizedName":"Cyan Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:cyan_stained_glass","unlocalizedName":"block.minecraft.cyan_stained_glass","localizedName":"Cyan Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_stained_glass_pane","unlocalizedName":"block.minecraft.cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_terracotta","unlocalizedName":"block.minecraft.cyan_terracotta","localizedName":"Cyan Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:cyan_wool","unlocalizedName":"block.minecraft.cyan_wool","localizedName":"Cyan Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:damaged_anvil","unlocalizedName":"block.minecraft.damaged_anvil","localizedName":"Damaged Anvil","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dandelion","unlocalizedName":"block.minecraft.dandelion","localizedName":"Dandelion","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_boat","unlocalizedName":"item.minecraft.dark_oak_boat","localizedName":"Dark Oak Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:dark_oak_button","unlocalizedName":"block.minecraft.dark_oak_button","localizedName":"Dark Oak Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_door","unlocalizedName":"block.minecraft.dark_oak_door","localizedName":"Dark Oak Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_fence","unlocalizedName":"block.minecraft.dark_oak_fence","localizedName":"Dark Oak Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_fence_gate","unlocalizedName":"block.minecraft.dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_leaves","unlocalizedName":"block.minecraft.dark_oak_leaves","localizedName":"Dark Oak Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_log","unlocalizedName":"block.minecraft.dark_oak_log","localizedName":"Dark Oak Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_planks","unlocalizedName":"block.minecraft.dark_oak_planks","localizedName":"Dark Oak Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_pressure_plate","unlocalizedName":"block.minecraft.dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_sapling","unlocalizedName":"block.minecraft.dark_oak_sapling","localizedName":"Dark Oak Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_sign","unlocalizedName":"block.minecraft.dark_oak_sign","localizedName":"Dark Oak Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:dark_oak_slab","unlocalizedName":"block.minecraft.dark_oak_slab","localizedName":"Dark Oak Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_stairs","unlocalizedName":"block.minecraft.dark_oak_stairs","localizedName":"Dark Oak Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_trapdoor","unlocalizedName":"block.minecraft.dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_oak_wood","unlocalizedName":"block.minecraft.dark_oak_wood","localizedName":"Dark Oak Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_prismarine","unlocalizedName":"block.minecraft.dark_prismarine","localizedName":"Dark Prismarine","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_prismarine_slab","unlocalizedName":"block.minecraft.dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dark_prismarine_stairs","unlocalizedName":"block.minecraft.dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:daylight_detector","unlocalizedName":"block.minecraft.daylight_detector","localizedName":"Daylight Detector","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_brain_coral","unlocalizedName":"block.minecraft.dead_brain_coral","localizedName":"Dead Brain Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_brain_coral_block","unlocalizedName":"block.minecraft.dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_brain_coral_fan","unlocalizedName":"block.minecraft.dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_bubble_coral","unlocalizedName":"block.minecraft.dead_bubble_coral","localizedName":"Dead Bubble Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_bubble_coral_block","unlocalizedName":"block.minecraft.dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_bubble_coral_fan","unlocalizedName":"block.minecraft.dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_bush","unlocalizedName":"block.minecraft.dead_bush","localizedName":"Dead Bush","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_fire_coral","unlocalizedName":"block.minecraft.dead_fire_coral","localizedName":"Dead Fire Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_fire_coral_block","unlocalizedName":"block.minecraft.dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_fire_coral_fan","unlocalizedName":"block.minecraft.dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_horn_coral","unlocalizedName":"block.minecraft.dead_horn_coral","localizedName":"Dead Horn Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_horn_coral_block","unlocalizedName":"block.minecraft.dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_horn_coral_fan","unlocalizedName":"block.minecraft.dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_tube_coral","unlocalizedName":"block.minecraft.dead_tube_coral","localizedName":"Dead Tube Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_tube_coral_block","unlocalizedName":"block.minecraft.dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dead_tube_coral_fan","unlocalizedName":"block.minecraft.dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:debug_stick","unlocalizedName":"item.minecraft.debug_stick","localizedName":"Debug Stick","maxDamage":0,"maxStackSize":1},{"id":"minecraft:detector_rail","unlocalizedName":"block.minecraft.detector_rail","localizedName":"Detector Rail","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diamond","unlocalizedName":"item.minecraft.diamond","localizedName":"Diamond","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diamond_axe","unlocalizedName":"item.minecraft.diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1},{"id":"minecraft:diamond_block","unlocalizedName":"block.minecraft.diamond_block","localizedName":"Block of Diamond","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diamond_boots","unlocalizedName":"item.minecraft.diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1},{"id":"minecraft:diamond_chestplate","unlocalizedName":"item.minecraft.diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1},{"id":"minecraft:diamond_helmet","unlocalizedName":"item.minecraft.diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1},{"id":"minecraft:diamond_hoe","unlocalizedName":"item.minecraft.diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1},{"id":"minecraft:diamond_horse_armor","unlocalizedName":"item.minecraft.diamond_horse_armor","localizedName":"Diamond Horse Armor","maxDamage":0,"maxStackSize":1},{"id":"minecraft:diamond_leggings","unlocalizedName":"item.minecraft.diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1},{"id":"minecraft:diamond_ore","unlocalizedName":"block.minecraft.diamond_ore","localizedName":"Diamond Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diamond_pickaxe","unlocalizedName":"item.minecraft.diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1},{"id":"minecraft:diamond_shovel","unlocalizedName":"item.minecraft.diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1},{"id":"minecraft:diamond_sword","unlocalizedName":"item.minecraft.diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1},{"id":"minecraft:diorite","unlocalizedName":"block.minecraft.diorite","localizedName":"Diorite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diorite_slab","unlocalizedName":"block.minecraft.diorite_slab","localizedName":"Diorite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diorite_stairs","unlocalizedName":"block.minecraft.diorite_stairs","localizedName":"Diorite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:diorite_wall","unlocalizedName":"block.minecraft.diorite_wall","localizedName":"Diorite Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dirt","unlocalizedName":"block.minecraft.dirt","localizedName":"Dirt","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dispenser","unlocalizedName":"block.minecraft.dispenser","localizedName":"Dispenser","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dolphin_spawn_egg","unlocalizedName":"item.minecraft.dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:donkey_spawn_egg","unlocalizedName":"item.minecraft.donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dragon_breath","unlocalizedName":"item.minecraft.dragon_breath","localizedName":"Dragon's Breath","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dragon_egg","unlocalizedName":"block.minecraft.dragon_egg","localizedName":"Dragon Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dragon_head","unlocalizedName":"block.minecraft.dragon_head","localizedName":"Dragon Head","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dried_kelp","unlocalizedName":"item.minecraft.dried_kelp","localizedName":"Dried Kelp","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dried_kelp_block","unlocalizedName":"block.minecraft.dried_kelp_block","localizedName":"Dried Kelp Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:dropper","unlocalizedName":"block.minecraft.dropper","localizedName":"Dropper","maxDamage":0,"maxStackSize":64},{"id":"minecraft:drowned_spawn_egg","unlocalizedName":"item.minecraft.drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:egg","unlocalizedName":"item.minecraft.egg","localizedName":"Egg","maxDamage":0,"maxStackSize":16},{"id":"minecraft:elder_guardian_spawn_egg","unlocalizedName":"item.minecraft.elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:elytra","unlocalizedName":"item.minecraft.elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1},{"id":"minecraft:emerald","unlocalizedName":"item.minecraft.emerald","localizedName":"Emerald","maxDamage":0,"maxStackSize":64},{"id":"minecraft:emerald_block","unlocalizedName":"block.minecraft.emerald_block","localizedName":"Block of Emerald","maxDamage":0,"maxStackSize":64},{"id":"minecraft:emerald_ore","unlocalizedName":"block.minecraft.emerald_ore","localizedName":"Emerald Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:enchanted_book","unlocalizedName":"item.minecraft.enchanted_book","localizedName":"Enchanted Book","maxDamage":0,"maxStackSize":1},{"id":"minecraft:enchanted_golden_apple","unlocalizedName":"item.minecraft.enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxDamage":0,"maxStackSize":64},{"id":"minecraft:enchanting_table","unlocalizedName":"block.minecraft.enchanting_table","localizedName":"Enchanting Table","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_crystal","unlocalizedName":"item.minecraft.end_crystal","localizedName":"End Crystal","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_portal_frame","unlocalizedName":"block.minecraft.end_portal_frame","localizedName":"End Portal Frame","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_rod","unlocalizedName":"block.minecraft.end_rod","localizedName":"End Rod","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_stone","unlocalizedName":"block.minecraft.end_stone","localizedName":"End Stone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_stone_brick_slab","unlocalizedName":"block.minecraft.end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_stone_brick_stairs","unlocalizedName":"block.minecraft.end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_stone_brick_wall","unlocalizedName":"block.minecraft.end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:end_stone_bricks","unlocalizedName":"block.minecraft.end_stone_bricks","localizedName":"End Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ender_chest","unlocalizedName":"block.minecraft.ender_chest","localizedName":"Ender Chest","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ender_eye","unlocalizedName":"item.minecraft.ender_eye","localizedName":"Eye of Ender","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ender_pearl","unlocalizedName":"item.minecraft.ender_pearl","localizedName":"Ender Pearl","maxDamage":0,"maxStackSize":16},{"id":"minecraft:enderman_spawn_egg","unlocalizedName":"item.minecraft.enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:endermite_spawn_egg","unlocalizedName":"item.minecraft.endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:evoker_spawn_egg","unlocalizedName":"item.minecraft.evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:experience_bottle","unlocalizedName":"item.minecraft.experience_bottle","localizedName":"Bottle o' Enchanting","maxDamage":0,"maxStackSize":64},{"id":"minecraft:farmland","unlocalizedName":"block.minecraft.farmland","localizedName":"Farmland","maxDamage":0,"maxStackSize":64},{"id":"minecraft:feather","unlocalizedName":"item.minecraft.feather","localizedName":"Feather","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fermented_spider_eye","unlocalizedName":"item.minecraft.fermented_spider_eye","localizedName":"Fermented Spider Eye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fern","unlocalizedName":"block.minecraft.fern","localizedName":"Fern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:filled_map","unlocalizedName":"item.minecraft.filled_map","localizedName":"Map","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fire_charge","unlocalizedName":"item.minecraft.fire_charge","localizedName":"Fire Charge","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fire_coral","unlocalizedName":"block.minecraft.fire_coral","localizedName":"Fire Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fire_coral_block","unlocalizedName":"block.minecraft.fire_coral_block","localizedName":"Fire Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fire_coral_fan","unlocalizedName":"block.minecraft.fire_coral_fan","localizedName":"Fire Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:firework_rocket","unlocalizedName":"item.minecraft.firework_rocket","localizedName":"Firework Rocket","maxDamage":0,"maxStackSize":64},{"id":"minecraft:firework_star","unlocalizedName":"item.minecraft.firework_star","localizedName":"Firework Star","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fishing_rod","unlocalizedName":"item.minecraft.fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1},{"id":"minecraft:fletching_table","unlocalizedName":"block.minecraft.fletching_table","localizedName":"Fletching Table","maxDamage":0,"maxStackSize":64},{"id":"minecraft:flint","unlocalizedName":"item.minecraft.flint","localizedName":"Flint","maxDamage":0,"maxStackSize":64},{"id":"minecraft:flint_and_steel","unlocalizedName":"item.minecraft.flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1},{"id":"minecraft:flower_banner_pattern","unlocalizedName":"item.minecraft.flower_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1},{"id":"minecraft:flower_pot","unlocalizedName":"block.minecraft.flower_pot","localizedName":"Flower Pot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:fox_spawn_egg","unlocalizedName":"item.minecraft.fox_spawn_egg","localizedName":"Fox Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:furnace","unlocalizedName":"block.minecraft.furnace","localizedName":"Furnace","maxDamage":0,"maxStackSize":64},{"id":"minecraft:furnace_minecart","unlocalizedName":"item.minecraft.furnace_minecart","localizedName":"Minecart with Furnace","maxDamage":0,"maxStackSize":1},{"id":"minecraft:ghast_spawn_egg","unlocalizedName":"item.minecraft.ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ghast_tear","unlocalizedName":"item.minecraft.ghast_tear","localizedName":"Ghast Tear","maxDamage":0,"maxStackSize":64},{"id":"minecraft:glass","unlocalizedName":"block.minecraft.glass","localizedName":"Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:glass_bottle","unlocalizedName":"item.minecraft.glass_bottle","localizedName":"Glass Bottle","maxDamage":0,"maxStackSize":64},{"id":"minecraft:glass_pane","unlocalizedName":"block.minecraft.glass_pane","localizedName":"Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:glistering_melon_slice","unlocalizedName":"item.minecraft.glistering_melon_slice","localizedName":"Glistering Melon Slice","maxDamage":0,"maxStackSize":64},{"id":"minecraft:globe_banner_pattern","unlocalizedName":"item.minecraft.globe_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1},{"id":"minecraft:glowstone","unlocalizedName":"block.minecraft.glowstone","localizedName":"Glowstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:glowstone_dust","unlocalizedName":"item.minecraft.glowstone_dust","localizedName":"Glowstone Dust","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gold_block","unlocalizedName":"block.minecraft.gold_block","localizedName":"Block of Gold","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gold_ingot","unlocalizedName":"item.minecraft.gold_ingot","localizedName":"Gold Ingot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gold_nugget","unlocalizedName":"item.minecraft.gold_nugget","localizedName":"Gold Nugget","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gold_ore","unlocalizedName":"block.minecraft.gold_ore","localizedName":"Gold Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:golden_apple","unlocalizedName":"item.minecraft.golden_apple","localizedName":"Golden Apple","maxDamage":0,"maxStackSize":64},{"id":"minecraft:golden_axe","unlocalizedName":"item.minecraft.golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1},{"id":"minecraft:golden_boots","unlocalizedName":"item.minecraft.golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1},{"id":"minecraft:golden_carrot","unlocalizedName":"item.minecraft.golden_carrot","localizedName":"Golden Carrot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:golden_chestplate","unlocalizedName":"item.minecraft.golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1},{"id":"minecraft:golden_helmet","unlocalizedName":"item.minecraft.golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1},{"id":"minecraft:golden_hoe","unlocalizedName":"item.minecraft.golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1},{"id":"minecraft:golden_horse_armor","unlocalizedName":"item.minecraft.golden_horse_armor","localizedName":"Golden Horse Armor","maxDamage":0,"maxStackSize":1},{"id":"minecraft:golden_leggings","unlocalizedName":"item.minecraft.golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1},{"id":"minecraft:golden_pickaxe","unlocalizedName":"item.minecraft.golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1},{"id":"minecraft:golden_shovel","unlocalizedName":"item.minecraft.golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1},{"id":"minecraft:golden_sword","unlocalizedName":"item.minecraft.golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1},{"id":"minecraft:granite","unlocalizedName":"block.minecraft.granite","localizedName":"Granite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:granite_slab","unlocalizedName":"block.minecraft.granite_slab","localizedName":"Granite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:granite_stairs","unlocalizedName":"block.minecraft.granite_stairs","localizedName":"Granite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:granite_wall","unlocalizedName":"block.minecraft.granite_wall","localizedName":"Granite Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:grass","unlocalizedName":"block.minecraft.grass","localizedName":"Grass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:grass_block","unlocalizedName":"block.minecraft.grass_block","localizedName":"Grass Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:grass_path","unlocalizedName":"block.minecraft.grass_path","localizedName":"Grass Path","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gravel","unlocalizedName":"block.minecraft.gravel","localizedName":"Gravel","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_banner","unlocalizedName":"block.minecraft.gray_banner","localizedName":"Gray Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:gray_bed","unlocalizedName":"block.minecraft.gray_bed","localizedName":"Gray Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:gray_carpet","unlocalizedName":"block.minecraft.gray_carpet","localizedName":"Gray Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_concrete","unlocalizedName":"block.minecraft.gray_concrete","localizedName":"Gray Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_concrete_powder","unlocalizedName":"block.minecraft.gray_concrete_powder","localizedName":"Gray Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_dye","unlocalizedName":"item.minecraft.gray_dye","localizedName":"Gray Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_glazed_terracotta","unlocalizedName":"block.minecraft.gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_shulker_box","unlocalizedName":"block.minecraft.gray_shulker_box","localizedName":"Gray Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:gray_stained_glass","unlocalizedName":"block.minecraft.gray_stained_glass","localizedName":"Gray Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_stained_glass_pane","unlocalizedName":"block.minecraft.gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_terracotta","unlocalizedName":"block.minecraft.gray_terracotta","localizedName":"Gray Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gray_wool","unlocalizedName":"block.minecraft.gray_wool","localizedName":"Gray Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_banner","unlocalizedName":"block.minecraft.green_banner","localizedName":"Green Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:green_bed","unlocalizedName":"block.minecraft.green_bed","localizedName":"Green Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:green_carpet","unlocalizedName":"block.minecraft.green_carpet","localizedName":"Green Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_concrete","unlocalizedName":"block.minecraft.green_concrete","localizedName":"Green Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_concrete_powder","unlocalizedName":"block.minecraft.green_concrete_powder","localizedName":"Green Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_dye","unlocalizedName":"item.minecraft.green_dye","localizedName":"Green Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_glazed_terracotta","unlocalizedName":"block.minecraft.green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_shulker_box","unlocalizedName":"block.minecraft.green_shulker_box","localizedName":"Green Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:green_stained_glass","unlocalizedName":"block.minecraft.green_stained_glass","localizedName":"Green Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_stained_glass_pane","unlocalizedName":"block.minecraft.green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_terracotta","unlocalizedName":"block.minecraft.green_terracotta","localizedName":"Green Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:green_wool","unlocalizedName":"block.minecraft.green_wool","localizedName":"Green Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:grindstone","unlocalizedName":"block.minecraft.grindstone","localizedName":"Grindstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:guardian_spawn_egg","unlocalizedName":"item.minecraft.guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:gunpowder","unlocalizedName":"item.minecraft.gunpowder","localizedName":"Gunpowder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:hay_block","unlocalizedName":"block.minecraft.hay_block","localizedName":"Hay Bale","maxDamage":0,"maxStackSize":64},{"id":"minecraft:heart_of_the_sea","unlocalizedName":"item.minecraft.heart_of_the_sea","localizedName":"Heart of the Sea","maxDamage":0,"maxStackSize":64},{"id":"minecraft:heavy_weighted_pressure_plate","unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:honey_block","unlocalizedName":"block.minecraft.honey_block","localizedName":"Honey Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:honey_bottle","unlocalizedName":"item.minecraft.honey_bottle","localizedName":"Honey Bottle","maxDamage":0,"maxStackSize":16},{"id":"minecraft:honeycomb","unlocalizedName":"item.minecraft.honeycomb","localizedName":"Honeycomb","maxDamage":0,"maxStackSize":64},{"id":"minecraft:honeycomb_block","unlocalizedName":"block.minecraft.honeycomb_block","localizedName":"Honeycomb Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:hopper","unlocalizedName":"block.minecraft.hopper","localizedName":"Hopper","maxDamage":0,"maxStackSize":64},{"id":"minecraft:hopper_minecart","unlocalizedName":"item.minecraft.hopper_minecart","localizedName":"Minecart with Hopper","maxDamage":0,"maxStackSize":1},{"id":"minecraft:horn_coral","unlocalizedName":"block.minecraft.horn_coral","localizedName":"Horn Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:horn_coral_block","unlocalizedName":"block.minecraft.horn_coral_block","localizedName":"Horn Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:horn_coral_fan","unlocalizedName":"block.minecraft.horn_coral_fan","localizedName":"Horn Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:horse_spawn_egg","unlocalizedName":"item.minecraft.horse_spawn_egg","localizedName":"Horse Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:husk_spawn_egg","unlocalizedName":"item.minecraft.husk_spawn_egg","localizedName":"Husk Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ice","unlocalizedName":"block.minecraft.ice","localizedName":"Ice","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_chiseled_stone_bricks","unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_cobblestone","unlocalizedName":"block.minecraft.infested_cobblestone","localizedName":"Infested Cobblestone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_cracked_stone_bricks","unlocalizedName":"block.minecraft.infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_mossy_stone_bricks","unlocalizedName":"block.minecraft.infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_stone","unlocalizedName":"block.minecraft.infested_stone","localizedName":"Infested Stone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:infested_stone_bricks","unlocalizedName":"block.minecraft.infested_stone_bricks","localizedName":"Infested Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ink_sac","unlocalizedName":"item.minecraft.ink_sac","localizedName":"Ink Sac","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_axe","unlocalizedName":"item.minecraft.iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1},{"id":"minecraft:iron_bars","unlocalizedName":"block.minecraft.iron_bars","localizedName":"Iron Bars","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_block","unlocalizedName":"block.minecraft.iron_block","localizedName":"Block of Iron","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_boots","unlocalizedName":"item.minecraft.iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1},{"id":"minecraft:iron_chestplate","unlocalizedName":"item.minecraft.iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1},{"id":"minecraft:iron_door","unlocalizedName":"block.minecraft.iron_door","localizedName":"Iron Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_helmet","unlocalizedName":"item.minecraft.iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1},{"id":"minecraft:iron_hoe","unlocalizedName":"item.minecraft.iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1},{"id":"minecraft:iron_horse_armor","unlocalizedName":"item.minecraft.iron_horse_armor","localizedName":"Iron Horse Armor","maxDamage":0,"maxStackSize":1},{"id":"minecraft:iron_ingot","unlocalizedName":"item.minecraft.iron_ingot","localizedName":"Iron Ingot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_leggings","unlocalizedName":"item.minecraft.iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1},{"id":"minecraft:iron_nugget","unlocalizedName":"item.minecraft.iron_nugget","localizedName":"Iron Nugget","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_ore","unlocalizedName":"block.minecraft.iron_ore","localizedName":"Iron Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:iron_pickaxe","unlocalizedName":"item.minecraft.iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1},{"id":"minecraft:iron_shovel","unlocalizedName":"item.minecraft.iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1},{"id":"minecraft:iron_sword","unlocalizedName":"item.minecraft.iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1},{"id":"minecraft:iron_trapdoor","unlocalizedName":"block.minecraft.iron_trapdoor","localizedName":"Iron Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:item_frame","unlocalizedName":"item.minecraft.item_frame","localizedName":"Item Frame","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jack_o_lantern","unlocalizedName":"block.minecraft.jack_o_lantern","localizedName":"Jack o'Lantern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jigsaw","unlocalizedName":"block.minecraft.jigsaw","localizedName":"Jigsaw Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jukebox","unlocalizedName":"block.minecraft.jukebox","localizedName":"Jukebox","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_boat","unlocalizedName":"item.minecraft.jungle_boat","localizedName":"Jungle Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:jungle_button","unlocalizedName":"block.minecraft.jungle_button","localizedName":"Jungle Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_door","unlocalizedName":"block.minecraft.jungle_door","localizedName":"Jungle Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_fence","unlocalizedName":"block.minecraft.jungle_fence","localizedName":"Jungle Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_fence_gate","unlocalizedName":"block.minecraft.jungle_fence_gate","localizedName":"Jungle Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_leaves","unlocalizedName":"block.minecraft.jungle_leaves","localizedName":"Jungle Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_log","unlocalizedName":"block.minecraft.jungle_log","localizedName":"Jungle Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_planks","unlocalizedName":"block.minecraft.jungle_planks","localizedName":"Jungle Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_pressure_plate","unlocalizedName":"block.minecraft.jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_sapling","unlocalizedName":"block.minecraft.jungle_sapling","localizedName":"Jungle Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_sign","unlocalizedName":"block.minecraft.jungle_sign","localizedName":"Jungle Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:jungle_slab","unlocalizedName":"block.minecraft.jungle_slab","localizedName":"Jungle Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_stairs","unlocalizedName":"block.minecraft.jungle_stairs","localizedName":"Jungle Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_trapdoor","unlocalizedName":"block.minecraft.jungle_trapdoor","localizedName":"Jungle Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:jungle_wood","unlocalizedName":"block.minecraft.jungle_wood","localizedName":"Jungle Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:kelp","unlocalizedName":"block.minecraft.kelp","localizedName":"Kelp","maxDamage":0,"maxStackSize":64},{"id":"minecraft:knowledge_book","unlocalizedName":"item.minecraft.knowledge_book","localizedName":"Knowledge Book","maxDamage":0,"maxStackSize":1},{"id":"minecraft:ladder","unlocalizedName":"block.minecraft.ladder","localizedName":"Ladder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lantern","unlocalizedName":"block.minecraft.lantern","localizedName":"Lantern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lapis_block","unlocalizedName":"block.minecraft.lapis_block","localizedName":"Lapis Lazuli Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lapis_lazuli","unlocalizedName":"item.minecraft.lapis_lazuli","localizedName":"Lapis Lazuli","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lapis_ore","unlocalizedName":"block.minecraft.lapis_ore","localizedName":"Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:large_fern","unlocalizedName":"block.minecraft.large_fern","localizedName":"Large Fern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lava_bucket","unlocalizedName":"item.minecraft.lava_bucket","localizedName":"Lava Bucket","maxDamage":0,"maxStackSize":1},{"id":"minecraft:lead","unlocalizedName":"item.minecraft.lead","localizedName":"Lead","maxDamage":0,"maxStackSize":64},{"id":"minecraft:leather","unlocalizedName":"item.minecraft.leather","localizedName":"Leather","maxDamage":0,"maxStackSize":64},{"id":"minecraft:leather_boots","unlocalizedName":"item.minecraft.leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1},{"id":"minecraft:leather_chestplate","unlocalizedName":"item.minecraft.leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1},{"id":"minecraft:leather_helmet","unlocalizedName":"item.minecraft.leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1},{"id":"minecraft:leather_horse_armor","unlocalizedName":"item.minecraft.leather_horse_armor","localizedName":"Leather Horse Armor","maxDamage":0,"maxStackSize":1},{"id":"minecraft:leather_leggings","unlocalizedName":"item.minecraft.leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1},{"id":"minecraft:lectern","unlocalizedName":"block.minecraft.lectern","localizedName":"Lectern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lever","unlocalizedName":"block.minecraft.lever","localizedName":"Lever","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_banner","unlocalizedName":"block.minecraft.light_blue_banner","localizedName":"Light Blue Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:light_blue_bed","unlocalizedName":"block.minecraft.light_blue_bed","localizedName":"Light Blue Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:light_blue_carpet","unlocalizedName":"block.minecraft.light_blue_carpet","localizedName":"Light Blue Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_concrete","unlocalizedName":"block.minecraft.light_blue_concrete","localizedName":"Light Blue Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_concrete_powder","unlocalizedName":"block.minecraft.light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_dye","unlocalizedName":"item.minecraft.light_blue_dye","localizedName":"Light Blue Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_glazed_terracotta","unlocalizedName":"block.minecraft.light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_shulker_box","unlocalizedName":"block.minecraft.light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:light_blue_stained_glass","unlocalizedName":"block.minecraft.light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_stained_glass_pane","unlocalizedName":"block.minecraft.light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_terracotta","unlocalizedName":"block.minecraft.light_blue_terracotta","localizedName":"Light Blue Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_blue_wool","unlocalizedName":"block.minecraft.light_blue_wool","localizedName":"Light Blue Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_banner","unlocalizedName":"block.minecraft.light_gray_banner","localizedName":"Light Gray Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:light_gray_bed","unlocalizedName":"block.minecraft.light_gray_bed","localizedName":"Light Gray Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:light_gray_carpet","unlocalizedName":"block.minecraft.light_gray_carpet","localizedName":"Light Gray Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_concrete","unlocalizedName":"block.minecraft.light_gray_concrete","localizedName":"Light Gray Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_concrete_powder","unlocalizedName":"block.minecraft.light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_dye","unlocalizedName":"item.minecraft.light_gray_dye","localizedName":"Light Gray Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_glazed_terracotta","unlocalizedName":"block.minecraft.light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_shulker_box","unlocalizedName":"block.minecraft.light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:light_gray_stained_glass","unlocalizedName":"block.minecraft.light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_stained_glass_pane","unlocalizedName":"block.minecraft.light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_terracotta","unlocalizedName":"block.minecraft.light_gray_terracotta","localizedName":"Light Gray Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_gray_wool","unlocalizedName":"block.minecraft.light_gray_wool","localizedName":"Light Gray Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:light_weighted_pressure_plate","unlocalizedName":"block.minecraft.light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lilac","unlocalizedName":"block.minecraft.lilac","localizedName":"Lilac","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lily_of_the_valley","unlocalizedName":"block.minecraft.lily_of_the_valley","localizedName":"Lily of the Valley","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lily_pad","unlocalizedName":"block.minecraft.lily_pad","localizedName":"Lily Pad","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_banner","unlocalizedName":"block.minecraft.lime_banner","localizedName":"Lime Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:lime_bed","unlocalizedName":"block.minecraft.lime_bed","localizedName":"Lime Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:lime_carpet","unlocalizedName":"block.minecraft.lime_carpet","localizedName":"Lime Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_concrete","unlocalizedName":"block.minecraft.lime_concrete","localizedName":"Lime Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_concrete_powder","unlocalizedName":"block.minecraft.lime_concrete_powder","localizedName":"Lime Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_dye","unlocalizedName":"item.minecraft.lime_dye","localizedName":"Lime Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_glazed_terracotta","unlocalizedName":"block.minecraft.lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_shulker_box","unlocalizedName":"block.minecraft.lime_shulker_box","localizedName":"Lime Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:lime_stained_glass","unlocalizedName":"block.minecraft.lime_stained_glass","localizedName":"Lime Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_stained_glass_pane","unlocalizedName":"block.minecraft.lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_terracotta","unlocalizedName":"block.minecraft.lime_terracotta","localizedName":"Lime Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lime_wool","unlocalizedName":"block.minecraft.lime_wool","localizedName":"Lime Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:lingering_potion","unlocalizedName":"item.minecraft.lingering_potion.effect.water","localizedName":"Lingering Water Bottle","maxDamage":0,"maxStackSize":1},{"id":"minecraft:llama_spawn_egg","unlocalizedName":"item.minecraft.llama_spawn_egg","localizedName":"Llama Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:loom","unlocalizedName":"block.minecraft.loom","localizedName":"Loom","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_banner","unlocalizedName":"block.minecraft.magenta_banner","localizedName":"Magenta Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:magenta_bed","unlocalizedName":"block.minecraft.magenta_bed","localizedName":"Magenta Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:magenta_carpet","unlocalizedName":"block.minecraft.magenta_carpet","localizedName":"Magenta Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_concrete","unlocalizedName":"block.minecraft.magenta_concrete","localizedName":"Magenta Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_concrete_powder","unlocalizedName":"block.minecraft.magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_dye","unlocalizedName":"item.minecraft.magenta_dye","localizedName":"Magenta Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_glazed_terracotta","unlocalizedName":"block.minecraft.magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_shulker_box","unlocalizedName":"block.minecraft.magenta_shulker_box","localizedName":"Magenta Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:magenta_stained_glass","unlocalizedName":"block.minecraft.magenta_stained_glass","localizedName":"Magenta Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_stained_glass_pane","unlocalizedName":"block.minecraft.magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_terracotta","unlocalizedName":"block.minecraft.magenta_terracotta","localizedName":"Magenta Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magenta_wool","unlocalizedName":"block.minecraft.magenta_wool","localizedName":"Magenta Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magma_block","unlocalizedName":"block.minecraft.magma_block","localizedName":"Magma Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magma_cream","unlocalizedName":"item.minecraft.magma_cream","localizedName":"Magma Cream","maxDamage":0,"maxStackSize":64},{"id":"minecraft:magma_cube_spawn_egg","unlocalizedName":"item.minecraft.magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:map","unlocalizedName":"item.minecraft.map","localizedName":"Empty Map","maxDamage":0,"maxStackSize":64},{"id":"minecraft:melon","unlocalizedName":"block.minecraft.melon","localizedName":"Melon","maxDamage":0,"maxStackSize":64},{"id":"minecraft:melon_seeds","unlocalizedName":"item.minecraft.melon_seeds","localizedName":"Melon Seeds","maxDamage":0,"maxStackSize":64},{"id":"minecraft:melon_slice","unlocalizedName":"item.minecraft.melon_slice","localizedName":"Melon Slice","maxDamage":0,"maxStackSize":64},{"id":"minecraft:milk_bucket","unlocalizedName":"item.minecraft.milk_bucket","localizedName":"Milk Bucket","maxDamage":0,"maxStackSize":1},{"id":"minecraft:minecart","unlocalizedName":"item.minecraft.minecart","localizedName":"Minecart","maxDamage":0,"maxStackSize":1},{"id":"minecraft:mojang_banner_pattern","unlocalizedName":"item.minecraft.mojang_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1},{"id":"minecraft:mooshroom_spawn_egg","unlocalizedName":"item.minecraft.mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_cobblestone","unlocalizedName":"block.minecraft.mossy_cobblestone","localizedName":"Mossy Cobblestone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_cobblestone_slab","unlocalizedName":"block.minecraft.mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_cobblestone_stairs","unlocalizedName":"block.minecraft.mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_cobblestone_wall","unlocalizedName":"block.minecraft.mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_stone_brick_slab","unlocalizedName":"block.minecraft.mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_stone_brick_stairs","unlocalizedName":"block.minecraft.mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_stone_brick_wall","unlocalizedName":"block.minecraft.mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mossy_stone_bricks","unlocalizedName":"block.minecraft.mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mule_spawn_egg","unlocalizedName":"item.minecraft.mule_spawn_egg","localizedName":"Mule Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mushroom_stem","unlocalizedName":"block.minecraft.mushroom_stem","localizedName":"Mushroom Stem","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mushroom_stew","unlocalizedName":"item.minecraft.mushroom_stew","localizedName":"Mushroom Stew","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_11","unlocalizedName":"item.minecraft.music_disc_11","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_13","unlocalizedName":"item.minecraft.music_disc_13","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_blocks","unlocalizedName":"item.minecraft.music_disc_blocks","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_cat","unlocalizedName":"item.minecraft.music_disc_cat","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_chirp","unlocalizedName":"item.minecraft.music_disc_chirp","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_far","unlocalizedName":"item.minecraft.music_disc_far","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_mall","unlocalizedName":"item.minecraft.music_disc_mall","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_mellohi","unlocalizedName":"item.minecraft.music_disc_mellohi","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_stal","unlocalizedName":"item.minecraft.music_disc_stal","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_strad","unlocalizedName":"item.minecraft.music_disc_strad","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_wait","unlocalizedName":"item.minecraft.music_disc_wait","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:music_disc_ward","unlocalizedName":"item.minecraft.music_disc_ward","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1},{"id":"minecraft:mutton","unlocalizedName":"item.minecraft.mutton","localizedName":"Raw Mutton","maxDamage":0,"maxStackSize":64},{"id":"minecraft:mycelium","unlocalizedName":"block.minecraft.mycelium","localizedName":"Mycelium","maxDamage":0,"maxStackSize":64},{"id":"minecraft:name_tag","unlocalizedName":"item.minecraft.name_tag","localizedName":"Name Tag","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nautilus_shell","unlocalizedName":"item.minecraft.nautilus_shell","localizedName":"Nautilus Shell","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_brick","unlocalizedName":"item.minecraft.nether_brick","localizedName":"Nether Brick","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_brick_fence","unlocalizedName":"block.minecraft.nether_brick_fence","localizedName":"Nether Brick Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_brick_slab","unlocalizedName":"block.minecraft.nether_brick_slab","localizedName":"Nether Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_brick_stairs","unlocalizedName":"block.minecraft.nether_brick_stairs","localizedName":"Nether Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_brick_wall","unlocalizedName":"block.minecraft.nether_brick_wall","localizedName":"Nether Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_bricks","unlocalizedName":"block.minecraft.nether_bricks","localizedName":"Nether Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_quartz_ore","unlocalizedName":"block.minecraft.nether_quartz_ore","localizedName":"Nether Quartz Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_star","unlocalizedName":"item.minecraft.nether_star","localizedName":"Nether Star","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_wart","unlocalizedName":"item.minecraft.nether_wart","localizedName":"Nether Wart","maxDamage":0,"maxStackSize":64},{"id":"minecraft:nether_wart_block","unlocalizedName":"block.minecraft.nether_wart_block","localizedName":"Nether Wart Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:netherrack","unlocalizedName":"block.minecraft.netherrack","localizedName":"Netherrack","maxDamage":0,"maxStackSize":64},{"id":"minecraft:note_block","unlocalizedName":"block.minecraft.note_block","localizedName":"Note Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_boat","unlocalizedName":"item.minecraft.oak_boat","localizedName":"Oak Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:oak_button","unlocalizedName":"block.minecraft.oak_button","localizedName":"Oak Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_door","unlocalizedName":"block.minecraft.oak_door","localizedName":"Oak Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_fence","unlocalizedName":"block.minecraft.oak_fence","localizedName":"Oak Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_fence_gate","unlocalizedName":"block.minecraft.oak_fence_gate","localizedName":"Oak Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_leaves","unlocalizedName":"block.minecraft.oak_leaves","localizedName":"Oak Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_log","unlocalizedName":"block.minecraft.oak_log","localizedName":"Oak Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_planks","unlocalizedName":"block.minecraft.oak_planks","localizedName":"Oak Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_pressure_plate","unlocalizedName":"block.minecraft.oak_pressure_plate","localizedName":"Oak Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_sapling","unlocalizedName":"block.minecraft.oak_sapling","localizedName":"Oak Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_sign","unlocalizedName":"block.minecraft.oak_sign","localizedName":"Oak Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:oak_slab","unlocalizedName":"block.minecraft.oak_slab","localizedName":"Oak Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_stairs","unlocalizedName":"block.minecraft.oak_stairs","localizedName":"Oak Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_trapdoor","unlocalizedName":"block.minecraft.oak_trapdoor","localizedName":"Oak Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oak_wood","unlocalizedName":"block.minecraft.oak_wood","localizedName":"Oak Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:observer","unlocalizedName":"block.minecraft.observer","localizedName":"Observer","maxDamage":0,"maxStackSize":64},{"id":"minecraft:obsidian","unlocalizedName":"block.minecraft.obsidian","localizedName":"Obsidian","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ocelot_spawn_egg","unlocalizedName":"item.minecraft.ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_banner","unlocalizedName":"block.minecraft.orange_banner","localizedName":"Orange Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:orange_bed","unlocalizedName":"block.minecraft.orange_bed","localizedName":"Orange Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:orange_carpet","unlocalizedName":"block.minecraft.orange_carpet","localizedName":"Orange Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_concrete","unlocalizedName":"block.minecraft.orange_concrete","localizedName":"Orange Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_concrete_powder","unlocalizedName":"block.minecraft.orange_concrete_powder","localizedName":"Orange Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_dye","unlocalizedName":"item.minecraft.orange_dye","localizedName":"Orange Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_glazed_terracotta","unlocalizedName":"block.minecraft.orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_shulker_box","unlocalizedName":"block.minecraft.orange_shulker_box","localizedName":"Orange Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:orange_stained_glass","unlocalizedName":"block.minecraft.orange_stained_glass","localizedName":"Orange Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_stained_glass_pane","unlocalizedName":"block.minecraft.orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_terracotta","unlocalizedName":"block.minecraft.orange_terracotta","localizedName":"Orange Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_tulip","unlocalizedName":"block.minecraft.orange_tulip","localizedName":"Orange Tulip","maxDamage":0,"maxStackSize":64},{"id":"minecraft:orange_wool","unlocalizedName":"block.minecraft.orange_wool","localizedName":"Orange Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:oxeye_daisy","unlocalizedName":"block.minecraft.oxeye_daisy","localizedName":"Oxeye Daisy","maxDamage":0,"maxStackSize":64},{"id":"minecraft:packed_ice","unlocalizedName":"block.minecraft.packed_ice","localizedName":"Packed Ice","maxDamage":0,"maxStackSize":64},{"id":"minecraft:painting","unlocalizedName":"item.minecraft.painting","localizedName":"Painting","maxDamage":0,"maxStackSize":64},{"id":"minecraft:panda_spawn_egg","unlocalizedName":"item.minecraft.panda_spawn_egg","localizedName":"Panda Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:paper","unlocalizedName":"item.minecraft.paper","localizedName":"Paper","maxDamage":0,"maxStackSize":64},{"id":"minecraft:parrot_spawn_egg","unlocalizedName":"item.minecraft.parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:peony","unlocalizedName":"block.minecraft.peony","localizedName":"Peony","maxDamage":0,"maxStackSize":64},{"id":"minecraft:petrified_oak_slab","unlocalizedName":"block.minecraft.petrified_oak_slab","localizedName":"Petrified Oak Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:phantom_membrane","unlocalizedName":"item.minecraft.phantom_membrane","localizedName":"Phantom Membrane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:phantom_spawn_egg","unlocalizedName":"item.minecraft.phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pig_spawn_egg","unlocalizedName":"item.minecraft.pig_spawn_egg","localizedName":"Pig Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pillager_spawn_egg","unlocalizedName":"item.minecraft.pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_banner","unlocalizedName":"block.minecraft.pink_banner","localizedName":"Pink Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:pink_bed","unlocalizedName":"block.minecraft.pink_bed","localizedName":"Pink Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:pink_carpet","unlocalizedName":"block.minecraft.pink_carpet","localizedName":"Pink Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_concrete","unlocalizedName":"block.minecraft.pink_concrete","localizedName":"Pink Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_concrete_powder","unlocalizedName":"block.minecraft.pink_concrete_powder","localizedName":"Pink Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_dye","unlocalizedName":"item.minecraft.pink_dye","localizedName":"Pink Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_glazed_terracotta","unlocalizedName":"block.minecraft.pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_shulker_box","unlocalizedName":"block.minecraft.pink_shulker_box","localizedName":"Pink Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:pink_stained_glass","unlocalizedName":"block.minecraft.pink_stained_glass","localizedName":"Pink Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_stained_glass_pane","unlocalizedName":"block.minecraft.pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_terracotta","unlocalizedName":"block.minecraft.pink_terracotta","localizedName":"Pink Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_tulip","unlocalizedName":"block.minecraft.pink_tulip","localizedName":"Pink Tulip","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pink_wool","unlocalizedName":"block.minecraft.pink_wool","localizedName":"Pink Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:piston","unlocalizedName":"block.minecraft.piston","localizedName":"Piston","maxDamage":0,"maxStackSize":64},{"id":"minecraft:player_head","unlocalizedName":"block.minecraft.player_head","localizedName":"Player Head","maxDamage":0,"maxStackSize":64},{"id":"minecraft:podzol","unlocalizedName":"block.minecraft.podzol","localizedName":"Podzol","maxDamage":0,"maxStackSize":64},{"id":"minecraft:poisonous_potato","unlocalizedName":"item.minecraft.poisonous_potato","localizedName":"Poisonous Potato","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polar_bear_spawn_egg","unlocalizedName":"item.minecraft.polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_andesite","unlocalizedName":"block.minecraft.polished_andesite","localizedName":"Polished Andesite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_andesite_slab","unlocalizedName":"block.minecraft.polished_andesite_slab","localizedName":"Polished Andesite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_andesite_stairs","unlocalizedName":"block.minecraft.polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_diorite","unlocalizedName":"block.minecraft.polished_diorite","localizedName":"Polished Diorite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_diorite_slab","unlocalizedName":"block.minecraft.polished_diorite_slab","localizedName":"Polished Diorite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_diorite_stairs","unlocalizedName":"block.minecraft.polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_granite","unlocalizedName":"block.minecraft.polished_granite","localizedName":"Polished Granite","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_granite_slab","unlocalizedName":"block.minecraft.polished_granite_slab","localizedName":"Polished Granite Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:polished_granite_stairs","unlocalizedName":"block.minecraft.polished_granite_stairs","localizedName":"Polished Granite Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:popped_chorus_fruit","unlocalizedName":"item.minecraft.popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxDamage":0,"maxStackSize":64},{"id":"minecraft:poppy","unlocalizedName":"block.minecraft.poppy","localizedName":"Poppy","maxDamage":0,"maxStackSize":64},{"id":"minecraft:porkchop","unlocalizedName":"item.minecraft.porkchop","localizedName":"Raw Porkchop","maxDamage":0,"maxStackSize":64},{"id":"minecraft:potato","unlocalizedName":"item.minecraft.potato","localizedName":"Potato","maxDamage":0,"maxStackSize":64},{"id":"minecraft:potion","unlocalizedName":"item.minecraft.potion.effect.water","localizedName":"Water Bottle","maxDamage":0,"maxStackSize":1},{"id":"minecraft:powered_rail","unlocalizedName":"block.minecraft.powered_rail","localizedName":"Powered Rail","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine","unlocalizedName":"block.minecraft.prismarine","localizedName":"Prismarine","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_brick_slab","unlocalizedName":"block.minecraft.prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_brick_stairs","unlocalizedName":"block.minecraft.prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_bricks","unlocalizedName":"block.minecraft.prismarine_bricks","localizedName":"Prismarine Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_crystals","unlocalizedName":"item.minecraft.prismarine_crystals","localizedName":"Prismarine Crystals","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_shard","unlocalizedName":"item.minecraft.prismarine_shard","localizedName":"Prismarine Shard","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_slab","unlocalizedName":"block.minecraft.prismarine_slab","localizedName":"Prismarine Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_stairs","unlocalizedName":"block.minecraft.prismarine_stairs","localizedName":"Prismarine Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:prismarine_wall","unlocalizedName":"block.minecraft.prismarine_wall","localizedName":"Prismarine Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pufferfish","unlocalizedName":"item.minecraft.pufferfish","localizedName":"Pufferfish","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pufferfish_bucket","unlocalizedName":"item.minecraft.pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxDamage":0,"maxStackSize":1},{"id":"minecraft:pufferfish_spawn_egg","unlocalizedName":"item.minecraft.pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pumpkin","unlocalizedName":"block.minecraft.pumpkin","localizedName":"Pumpkin","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pumpkin_pie","unlocalizedName":"item.minecraft.pumpkin_pie","localizedName":"Pumpkin Pie","maxDamage":0,"maxStackSize":64},{"id":"minecraft:pumpkin_seeds","unlocalizedName":"item.minecraft.pumpkin_seeds","localizedName":"Pumpkin Seeds","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_banner","unlocalizedName":"block.minecraft.purple_banner","localizedName":"Purple Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:purple_bed","unlocalizedName":"block.minecraft.purple_bed","localizedName":"Purple Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:purple_carpet","unlocalizedName":"block.minecraft.purple_carpet","localizedName":"Purple Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_concrete","unlocalizedName":"block.minecraft.purple_concrete","localizedName":"Purple Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_concrete_powder","unlocalizedName":"block.minecraft.purple_concrete_powder","localizedName":"Purple Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_dye","unlocalizedName":"item.minecraft.purple_dye","localizedName":"Purple Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_glazed_terracotta","unlocalizedName":"block.minecraft.purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_shulker_box","unlocalizedName":"block.minecraft.purple_shulker_box","localizedName":"Purple Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:purple_stained_glass","unlocalizedName":"block.minecraft.purple_stained_glass","localizedName":"Purple Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_stained_glass_pane","unlocalizedName":"block.minecraft.purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_terracotta","unlocalizedName":"block.minecraft.purple_terracotta","localizedName":"Purple Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purple_wool","unlocalizedName":"block.minecraft.purple_wool","localizedName":"Purple Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purpur_block","unlocalizedName":"block.minecraft.purpur_block","localizedName":"Purpur Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purpur_pillar","unlocalizedName":"block.minecraft.purpur_pillar","localizedName":"Purpur Pillar","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purpur_slab","unlocalizedName":"block.minecraft.purpur_slab","localizedName":"Purpur Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:purpur_stairs","unlocalizedName":"block.minecraft.purpur_stairs","localizedName":"Purpur Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:quartz","unlocalizedName":"item.minecraft.quartz","localizedName":"Nether Quartz","maxDamage":0,"maxStackSize":64},{"id":"minecraft:quartz_block","unlocalizedName":"block.minecraft.quartz_block","localizedName":"Block of Quartz","maxDamage":0,"maxStackSize":64},{"id":"minecraft:quartz_pillar","unlocalizedName":"block.minecraft.quartz_pillar","localizedName":"Quartz Pillar","maxDamage":0,"maxStackSize":64},{"id":"minecraft:quartz_slab","unlocalizedName":"block.minecraft.quartz_slab","localizedName":"Quartz Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:quartz_stairs","unlocalizedName":"block.minecraft.quartz_stairs","localizedName":"Quartz Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rabbit","unlocalizedName":"item.minecraft.rabbit","localizedName":"Raw Rabbit","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rabbit_foot","unlocalizedName":"item.minecraft.rabbit_foot","localizedName":"Rabbit's Foot","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rabbit_hide","unlocalizedName":"item.minecraft.rabbit_hide","localizedName":"Rabbit Hide","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rabbit_spawn_egg","unlocalizedName":"item.minecraft.rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rabbit_stew","unlocalizedName":"item.minecraft.rabbit_stew","localizedName":"Rabbit Stew","maxDamage":0,"maxStackSize":1},{"id":"minecraft:rail","unlocalizedName":"block.minecraft.rail","localizedName":"Rail","maxDamage":0,"maxStackSize":64},{"id":"minecraft:ravager_spawn_egg","unlocalizedName":"item.minecraft.ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_banner","unlocalizedName":"block.minecraft.red_banner","localizedName":"Red Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:red_bed","unlocalizedName":"block.minecraft.red_bed","localizedName":"Red Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:red_carpet","unlocalizedName":"block.minecraft.red_carpet","localizedName":"Red Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_concrete","unlocalizedName":"block.minecraft.red_concrete","localizedName":"Red Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_concrete_powder","unlocalizedName":"block.minecraft.red_concrete_powder","localizedName":"Red Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_dye","unlocalizedName":"item.minecraft.red_dye","localizedName":"Red Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_glazed_terracotta","unlocalizedName":"block.minecraft.red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_mushroom","unlocalizedName":"block.minecraft.red_mushroom","localizedName":"Red Mushroom","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_mushroom_block","unlocalizedName":"block.minecraft.red_mushroom_block","localizedName":"Red Mushroom Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_nether_brick_slab","unlocalizedName":"block.minecraft.red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_nether_brick_stairs","unlocalizedName":"block.minecraft.red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_nether_brick_wall","unlocalizedName":"block.minecraft.red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_nether_bricks","unlocalizedName":"block.minecraft.red_nether_bricks","localizedName":"Red Nether Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_sand","unlocalizedName":"block.minecraft.red_sand","localizedName":"Red Sand","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_sandstone","unlocalizedName":"block.minecraft.red_sandstone","localizedName":"Red Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_sandstone_slab","unlocalizedName":"block.minecraft.red_sandstone_slab","localizedName":"Red Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_sandstone_stairs","unlocalizedName":"block.minecraft.red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_sandstone_wall","unlocalizedName":"block.minecraft.red_sandstone_wall","localizedName":"Red Sandstone Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_shulker_box","unlocalizedName":"block.minecraft.red_shulker_box","localizedName":"Red Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:red_stained_glass","unlocalizedName":"block.minecraft.red_stained_glass","localizedName":"Red Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_stained_glass_pane","unlocalizedName":"block.minecraft.red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_terracotta","unlocalizedName":"block.minecraft.red_terracotta","localizedName":"Red Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_tulip","unlocalizedName":"block.minecraft.red_tulip","localizedName":"Red Tulip","maxDamage":0,"maxStackSize":64},{"id":"minecraft:red_wool","unlocalizedName":"block.minecraft.red_wool","localizedName":"Red Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:redstone","unlocalizedName":"item.minecraft.redstone","localizedName":"Redstone Dust","maxDamage":0,"maxStackSize":64},{"id":"minecraft:redstone_block","unlocalizedName":"block.minecraft.redstone_block","localizedName":"Block of Redstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:redstone_lamp","unlocalizedName":"block.minecraft.redstone_lamp","localizedName":"Redstone Lamp","maxDamage":0,"maxStackSize":64},{"id":"minecraft:redstone_ore","unlocalizedName":"block.minecraft.redstone_ore","localizedName":"Redstone Ore","maxDamage":0,"maxStackSize":64},{"id":"minecraft:redstone_torch","unlocalizedName":"block.minecraft.redstone_torch","localizedName":"Redstone Torch","maxDamage":0,"maxStackSize":64},{"id":"minecraft:repeater","unlocalizedName":"block.minecraft.repeater","localizedName":"Redstone Repeater","maxDamage":0,"maxStackSize":64},{"id":"minecraft:repeating_command_block","unlocalizedName":"block.minecraft.repeating_command_block","localizedName":"Repeating Command Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rose_bush","unlocalizedName":"block.minecraft.rose_bush","localizedName":"Rose Bush","maxDamage":0,"maxStackSize":64},{"id":"minecraft:rotten_flesh","unlocalizedName":"item.minecraft.rotten_flesh","localizedName":"Rotten Flesh","maxDamage":0,"maxStackSize":64},{"id":"minecraft:saddle","unlocalizedName":"item.minecraft.saddle","localizedName":"Saddle","maxDamage":0,"maxStackSize":1},{"id":"minecraft:salmon","unlocalizedName":"item.minecraft.salmon","localizedName":"Raw Salmon","maxDamage":0,"maxStackSize":64},{"id":"minecraft:salmon_bucket","unlocalizedName":"item.minecraft.salmon_bucket","localizedName":"Bucket of Salmon","maxDamage":0,"maxStackSize":1},{"id":"minecraft:salmon_spawn_egg","unlocalizedName":"item.minecraft.salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sand","unlocalizedName":"block.minecraft.sand","localizedName":"Sand","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sandstone","unlocalizedName":"block.minecraft.sandstone","localizedName":"Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sandstone_slab","unlocalizedName":"block.minecraft.sandstone_slab","localizedName":"Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sandstone_stairs","unlocalizedName":"block.minecraft.sandstone_stairs","localizedName":"Sandstone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sandstone_wall","unlocalizedName":"block.minecraft.sandstone_wall","localizedName":"Sandstone Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:scaffolding","unlocalizedName":"block.minecraft.scaffolding","localizedName":"Scaffolding","maxDamage":0,"maxStackSize":64},{"id":"minecraft:scute","unlocalizedName":"item.minecraft.scute","localizedName":"Scute","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sea_lantern","unlocalizedName":"block.minecraft.sea_lantern","localizedName":"Sea Lantern","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sea_pickle","unlocalizedName":"block.minecraft.sea_pickle","localizedName":"Sea Pickle","maxDamage":0,"maxStackSize":64},{"id":"minecraft:seagrass","unlocalizedName":"block.minecraft.seagrass","localizedName":"Seagrass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:shears","unlocalizedName":"item.minecraft.shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1},{"id":"minecraft:sheep_spawn_egg","unlocalizedName":"item.minecraft.sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:shield","unlocalizedName":"item.minecraft.shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1},{"id":"minecraft:shulker_box","unlocalizedName":"block.minecraft.shulker_box","localizedName":"Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:shulker_shell","unlocalizedName":"item.minecraft.shulker_shell","localizedName":"Shulker Shell","maxDamage":0,"maxStackSize":64},{"id":"minecraft:shulker_spawn_egg","unlocalizedName":"item.minecraft.shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:silverfish_spawn_egg","unlocalizedName":"item.minecraft.silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:skeleton_horse_spawn_egg","unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:skeleton_skull","unlocalizedName":"block.minecraft.skeleton_skull","localizedName":"Skeleton Skull","maxDamage":0,"maxStackSize":64},{"id":"minecraft:skeleton_spawn_egg","unlocalizedName":"item.minecraft.skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:skull_banner_pattern","unlocalizedName":"item.minecraft.skull_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1},{"id":"minecraft:slime_ball","unlocalizedName":"item.minecraft.slime_ball","localizedName":"Slimeball","maxDamage":0,"maxStackSize":64},{"id":"minecraft:slime_block","unlocalizedName":"block.minecraft.slime_block","localizedName":"Slime Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:slime_spawn_egg","unlocalizedName":"item.minecraft.slime_spawn_egg","localizedName":"Slime Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smithing_table","unlocalizedName":"block.minecraft.smithing_table","localizedName":"Smithing Table","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smoker","unlocalizedName":"block.minecraft.smoker","localizedName":"Smoker","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_quartz","unlocalizedName":"block.minecraft.smooth_quartz","localizedName":"Smooth Quartz","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_quartz_slab","unlocalizedName":"block.minecraft.smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_quartz_stairs","unlocalizedName":"block.minecraft.smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_red_sandstone","unlocalizedName":"block.minecraft.smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_red_sandstone_slab","unlocalizedName":"block.minecraft.smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_red_sandstone_stairs","unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_sandstone","unlocalizedName":"block.minecraft.smooth_sandstone","localizedName":"Smooth Sandstone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_sandstone_slab","unlocalizedName":"block.minecraft.smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_sandstone_stairs","unlocalizedName":"block.minecraft.smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_stone","unlocalizedName":"block.minecraft.smooth_stone","localizedName":"Smooth Stone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:smooth_stone_slab","unlocalizedName":"block.minecraft.smooth_stone_slab","localizedName":"Smooth Stone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:snow","unlocalizedName":"block.minecraft.snow","localizedName":"Snow","maxDamage":0,"maxStackSize":64},{"id":"minecraft:snow_block","unlocalizedName":"block.minecraft.snow_block","localizedName":"Snow Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:snowball","unlocalizedName":"item.minecraft.snowball","localizedName":"Snowball","maxDamage":0,"maxStackSize":16},{"id":"minecraft:soul_sand","unlocalizedName":"block.minecraft.soul_sand","localizedName":"Soul Sand","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spawner","unlocalizedName":"block.minecraft.spawner","localizedName":"Spawner","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spectral_arrow","unlocalizedName":"item.minecraft.spectral_arrow","localizedName":"Spectral Arrow","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spider_eye","unlocalizedName":"item.minecraft.spider_eye","localizedName":"Spider Eye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spider_spawn_egg","unlocalizedName":"item.minecraft.spider_spawn_egg","localizedName":"Spider Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:splash_potion","unlocalizedName":"item.minecraft.splash_potion.effect.water","localizedName":"Splash Water Bottle","maxDamage":0,"maxStackSize":1},{"id":"minecraft:sponge","unlocalizedName":"block.minecraft.sponge","localizedName":"Sponge","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_boat","unlocalizedName":"item.minecraft.spruce_boat","localizedName":"Spruce Boat","maxDamage":0,"maxStackSize":1},{"id":"minecraft:spruce_button","unlocalizedName":"block.minecraft.spruce_button","localizedName":"Spruce Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_door","unlocalizedName":"block.minecraft.spruce_door","localizedName":"Spruce Door","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_fence","unlocalizedName":"block.minecraft.spruce_fence","localizedName":"Spruce Fence","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_fence_gate","unlocalizedName":"block.minecraft.spruce_fence_gate","localizedName":"Spruce Fence Gate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_leaves","unlocalizedName":"block.minecraft.spruce_leaves","localizedName":"Spruce Leaves","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_log","unlocalizedName":"block.minecraft.spruce_log","localizedName":"Spruce Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_planks","unlocalizedName":"block.minecraft.spruce_planks","localizedName":"Spruce Planks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_pressure_plate","unlocalizedName":"block.minecraft.spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_sapling","unlocalizedName":"block.minecraft.spruce_sapling","localizedName":"Spruce Sapling","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_sign","unlocalizedName":"block.minecraft.spruce_sign","localizedName":"Spruce Sign","maxDamage":0,"maxStackSize":16},{"id":"minecraft:spruce_slab","unlocalizedName":"block.minecraft.spruce_slab","localizedName":"Spruce Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_stairs","unlocalizedName":"block.minecraft.spruce_stairs","localizedName":"Spruce Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_trapdoor","unlocalizedName":"block.minecraft.spruce_trapdoor","localizedName":"Spruce Trapdoor","maxDamage":0,"maxStackSize":64},{"id":"minecraft:spruce_wood","unlocalizedName":"block.minecraft.spruce_wood","localizedName":"Spruce Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:squid_spawn_egg","unlocalizedName":"item.minecraft.squid_spawn_egg","localizedName":"Squid Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stick","unlocalizedName":"item.minecraft.stick","localizedName":"Stick","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sticky_piston","unlocalizedName":"block.minecraft.sticky_piston","localizedName":"Sticky Piston","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone","unlocalizedName":"block.minecraft.stone","localizedName":"Stone","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_axe","unlocalizedName":"item.minecraft.stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1},{"id":"minecraft:stone_brick_slab","unlocalizedName":"block.minecraft.stone_brick_slab","localizedName":"Stone Brick Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_brick_stairs","unlocalizedName":"block.minecraft.stone_brick_stairs","localizedName":"Stone Brick Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_brick_wall","unlocalizedName":"block.minecraft.stone_brick_wall","localizedName":"Stone Brick Wall","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_bricks","unlocalizedName":"block.minecraft.stone_bricks","localizedName":"Stone Bricks","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_button","unlocalizedName":"block.minecraft.stone_button","localizedName":"Stone Button","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_hoe","unlocalizedName":"item.minecraft.stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1},{"id":"minecraft:stone_pickaxe","unlocalizedName":"item.minecraft.stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1},{"id":"minecraft:stone_pressure_plate","unlocalizedName":"block.minecraft.stone_pressure_plate","localizedName":"Stone Pressure Plate","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_shovel","unlocalizedName":"item.minecraft.stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1},{"id":"minecraft:stone_slab","unlocalizedName":"block.minecraft.stone_slab","localizedName":"Stone Slab","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_stairs","unlocalizedName":"block.minecraft.stone_stairs","localizedName":"Stone Stairs","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stone_sword","unlocalizedName":"item.minecraft.stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1},{"id":"minecraft:stonecutter","unlocalizedName":"block.minecraft.stonecutter","localizedName":"Stonecutter","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stray_spawn_egg","unlocalizedName":"item.minecraft.stray_spawn_egg","localizedName":"Stray Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:string","unlocalizedName":"item.minecraft.string","localizedName":"String","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_acacia_log","unlocalizedName":"block.minecraft.stripped_acacia_log","localizedName":"Stripped Acacia Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_acacia_wood","unlocalizedName":"block.minecraft.stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_birch_log","unlocalizedName":"block.minecraft.stripped_birch_log","localizedName":"Stripped Birch Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_birch_wood","unlocalizedName":"block.minecraft.stripped_birch_wood","localizedName":"Stripped Birch Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_dark_oak_log","unlocalizedName":"block.minecraft.stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_dark_oak_wood","unlocalizedName":"block.minecraft.stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_jungle_log","unlocalizedName":"block.minecraft.stripped_jungle_log","localizedName":"Stripped Jungle Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_jungle_wood","unlocalizedName":"block.minecraft.stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_oak_log","unlocalizedName":"block.minecraft.stripped_oak_log","localizedName":"Stripped Oak Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_oak_wood","unlocalizedName":"block.minecraft.stripped_oak_wood","localizedName":"Stripped Oak Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_spruce_log","unlocalizedName":"block.minecraft.stripped_spruce_log","localizedName":"Stripped Spruce Log","maxDamage":0,"maxStackSize":64},{"id":"minecraft:stripped_spruce_wood","unlocalizedName":"block.minecraft.stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxDamage":0,"maxStackSize":64},{"id":"minecraft:structure_block","unlocalizedName":"block.minecraft.structure_block","localizedName":"Structure Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:structure_void","unlocalizedName":"block.minecraft.structure_void","localizedName":"Structure Void","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sugar","unlocalizedName":"item.minecraft.sugar","localizedName":"Sugar","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sugar_cane","unlocalizedName":"block.minecraft.sugar_cane","localizedName":"Sugar Cane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:sunflower","unlocalizedName":"block.minecraft.sunflower","localizedName":"Sunflower","maxDamage":0,"maxStackSize":64},{"id":"minecraft:suspicious_stew","unlocalizedName":"item.minecraft.suspicious_stew","localizedName":"Suspicious Stew","maxDamage":0,"maxStackSize":1},{"id":"minecraft:sweet_berries","unlocalizedName":"item.minecraft.sweet_berries","localizedName":"Sweet Berries","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tall_grass","unlocalizedName":"block.minecraft.tall_grass","localizedName":"Tall Grass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:terracotta","unlocalizedName":"block.minecraft.terracotta","localizedName":"Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tipped_arrow","unlocalizedName":"item.minecraft.tipped_arrow.effect.poison","localizedName":"Arrow of Poison","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tnt","unlocalizedName":"block.minecraft.tnt","localizedName":"TNT","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tnt_minecart","unlocalizedName":"item.minecraft.tnt_minecart","localizedName":"Minecart with TNT","maxDamage":0,"maxStackSize":1},{"id":"minecraft:torch","unlocalizedName":"block.minecraft.torch","localizedName":"Torch","maxDamage":0,"maxStackSize":64},{"id":"minecraft:totem_of_undying","unlocalizedName":"item.minecraft.totem_of_undying","localizedName":"Totem of Undying","maxDamage":0,"maxStackSize":1},{"id":"minecraft:trader_llama_spawn_egg","unlocalizedName":"item.minecraft.trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:trapped_chest","unlocalizedName":"block.minecraft.trapped_chest","localizedName":"Trapped Chest","maxDamage":0,"maxStackSize":64},{"id":"minecraft:trident","unlocalizedName":"item.minecraft.trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1},{"id":"minecraft:tripwire_hook","unlocalizedName":"block.minecraft.tripwire_hook","localizedName":"Tripwire Hook","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tropical_fish","unlocalizedName":"item.minecraft.tropical_fish","localizedName":"Tropical Fish","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tropical_fish_bucket","unlocalizedName":"item.minecraft.tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxDamage":0,"maxStackSize":1},{"id":"minecraft:tropical_fish_spawn_egg","unlocalizedName":"item.minecraft.tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tube_coral","unlocalizedName":"block.minecraft.tube_coral","localizedName":"Tube Coral","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tube_coral_block","unlocalizedName":"block.minecraft.tube_coral_block","localizedName":"Tube Coral Block","maxDamage":0,"maxStackSize":64},{"id":"minecraft:tube_coral_fan","unlocalizedName":"block.minecraft.tube_coral_fan","localizedName":"Tube Coral Fan","maxDamage":0,"maxStackSize":64},{"id":"minecraft:turtle_egg","unlocalizedName":"block.minecraft.turtle_egg","localizedName":"Turtle Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:turtle_helmet","unlocalizedName":"item.minecraft.turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1},{"id":"minecraft:turtle_spawn_egg","unlocalizedName":"item.minecraft.turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:vex_spawn_egg","unlocalizedName":"item.minecraft.vex_spawn_egg","localizedName":"Vex Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:villager_spawn_egg","unlocalizedName":"item.minecraft.villager_spawn_egg","localizedName":"Villager Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:vindicator_spawn_egg","unlocalizedName":"item.minecraft.vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:vine","unlocalizedName":"block.minecraft.vine","localizedName":"Vines","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wandering_trader_spawn_egg","unlocalizedName":"item.minecraft.wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:water_bucket","unlocalizedName":"item.minecraft.water_bucket","localizedName":"Water Bucket","maxDamage":0,"maxStackSize":1},{"id":"minecraft:wet_sponge","unlocalizedName":"block.minecraft.wet_sponge","localizedName":"Wet Sponge","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wheat","unlocalizedName":"item.minecraft.wheat","localizedName":"Wheat","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wheat_seeds","unlocalizedName":"item.minecraft.wheat_seeds","localizedName":"Wheat Seeds","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_banner","unlocalizedName":"block.minecraft.white_banner","localizedName":"White Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:white_bed","unlocalizedName":"block.minecraft.white_bed","localizedName":"White Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:white_carpet","unlocalizedName":"block.minecraft.white_carpet","localizedName":"White Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_concrete","unlocalizedName":"block.minecraft.white_concrete","localizedName":"White Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_concrete_powder","unlocalizedName":"block.minecraft.white_concrete_powder","localizedName":"White Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_dye","unlocalizedName":"item.minecraft.white_dye","localizedName":"White Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_glazed_terracotta","unlocalizedName":"block.minecraft.white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_shulker_box","unlocalizedName":"block.minecraft.white_shulker_box","localizedName":"White Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:white_stained_glass","unlocalizedName":"block.minecraft.white_stained_glass","localizedName":"White Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_stained_glass_pane","unlocalizedName":"block.minecraft.white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_terracotta","unlocalizedName":"block.minecraft.white_terracotta","localizedName":"White Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_tulip","unlocalizedName":"block.minecraft.white_tulip","localizedName":"White Tulip","maxDamage":0,"maxStackSize":64},{"id":"minecraft:white_wool","unlocalizedName":"block.minecraft.white_wool","localizedName":"White Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:witch_spawn_egg","unlocalizedName":"item.minecraft.witch_spawn_egg","localizedName":"Witch Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wither_rose","unlocalizedName":"block.minecraft.wither_rose","localizedName":"Wither Rose","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wither_skeleton_skull","unlocalizedName":"block.minecraft.wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wither_skeleton_spawn_egg","unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wolf_spawn_egg","unlocalizedName":"item.minecraft.wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:wooden_axe","unlocalizedName":"item.minecraft.wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1},{"id":"minecraft:wooden_hoe","unlocalizedName":"item.minecraft.wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1},{"id":"minecraft:wooden_pickaxe","unlocalizedName":"item.minecraft.wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1},{"id":"minecraft:wooden_shovel","unlocalizedName":"item.minecraft.wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1},{"id":"minecraft:wooden_sword","unlocalizedName":"item.minecraft.wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1},{"id":"minecraft:writable_book","unlocalizedName":"item.minecraft.writable_book","localizedName":"Book and Quill","maxDamage":0,"maxStackSize":1},{"id":"minecraft:written_book","unlocalizedName":"item.minecraft.written_book","localizedName":"Written Book","maxDamage":0,"maxStackSize":16},{"id":"minecraft:yellow_banner","unlocalizedName":"block.minecraft.yellow_banner","localizedName":"Yellow Banner","maxDamage":0,"maxStackSize":16},{"id":"minecraft:yellow_bed","unlocalizedName":"block.minecraft.yellow_bed","localizedName":"Yellow Bed","maxDamage":0,"maxStackSize":1},{"id":"minecraft:yellow_carpet","unlocalizedName":"block.minecraft.yellow_carpet","localizedName":"Yellow Carpet","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_concrete","unlocalizedName":"block.minecraft.yellow_concrete","localizedName":"Yellow Concrete","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_concrete_powder","unlocalizedName":"block.minecraft.yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_dye","unlocalizedName":"item.minecraft.yellow_dye","localizedName":"Yellow Dye","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_glazed_terracotta","unlocalizedName":"block.minecraft.yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_shulker_box","unlocalizedName":"block.minecraft.yellow_shulker_box","localizedName":"Yellow Shulker Box","maxDamage":0,"maxStackSize":1},{"id":"minecraft:yellow_stained_glass","unlocalizedName":"block.minecraft.yellow_stained_glass","localizedName":"Yellow Stained Glass","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_stained_glass_pane","unlocalizedName":"block.minecraft.yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_terracotta","unlocalizedName":"block.minecraft.yellow_terracotta","localizedName":"Yellow Terracotta","maxDamage":0,"maxStackSize":64},{"id":"minecraft:yellow_wool","unlocalizedName":"block.minecraft.yellow_wool","localizedName":"Yellow Wool","maxDamage":0,"maxStackSize":64},{"id":"minecraft:zombie_head","unlocalizedName":"block.minecraft.zombie_head","localizedName":"Zombie Head","maxDamage":0,"maxStackSize":64},{"id":"minecraft:zombie_horse_spawn_egg","unlocalizedName":"item.minecraft.zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:zombie_pigman_spawn_egg","unlocalizedName":"item.minecraft.zombie_pigman_spawn_egg","localizedName":"Zombie Pigman Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:zombie_spawn_egg","unlocalizedName":"item.minecraft.zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxDamage":0,"maxStackSize":64},{"id":"minecraft:zombie_villager_spawn_egg","unlocalizedName":"item.minecraft.zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxDamage":0,"maxStackSize":64}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.116.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.116.json deleted file mode 100644 index 543059690..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.116.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_boat","localizedName":"Acacia Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_boat"},{"id":"minecraft:acacia_button","localizedName":"Acacia Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_button"},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_door"},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence"},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence_gate"},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_leaves"},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_log"},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_planks"},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_pressure_plate"},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_sapling"},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_sign"},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_slab"},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_stairs"},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_trapdoor"},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_wood"},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.activator_rail"},{"id":"minecraft:air","localizedName":"Air","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.air"},{"id":"minecraft:allium","localizedName":"Allium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.allium"},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ancient_debris"},{"id":"minecraft:andesite","localizedName":"Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite"},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_slab"},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_stairs"},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_wall"},{"id":"minecraft:anvil","localizedName":"Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.anvil"},{"id":"minecraft:apple","localizedName":"Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.apple"},{"id":"minecraft:armor_stand","localizedName":"Armor Stand","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.armor_stand"},{"id":"minecraft:arrow","localizedName":"Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.arrow"},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azure_bluet"},{"id":"minecraft:baked_potato","localizedName":"Baked Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.baked_potato"},{"id":"minecraft:bamboo","localizedName":"Bamboo","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo"},{"id":"minecraft:barrel","localizedName":"Barrel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrel"},{"id":"minecraft:barrier","localizedName":"Barrier","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrier"},{"id":"minecraft:basalt","localizedName":"Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.basalt"},{"id":"minecraft:bat_spawn_egg","localizedName":"Bat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bat_spawn_egg"},{"id":"minecraft:beacon","localizedName":"Beacon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beacon"},{"id":"minecraft:bedrock","localizedName":"Bedrock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bedrock"},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bee_nest"},{"id":"minecraft:bee_spawn_egg","localizedName":"Bee Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bee_spawn_egg"},{"id":"minecraft:beef","localizedName":"Raw Beef","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beef"},{"id":"minecraft:beehive","localizedName":"Beehive","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beehive"},{"id":"minecraft:beetroot","localizedName":"Beetroot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot"},{"id":"minecraft:beetroot_seeds","localizedName":"Beetroot Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot_seeds"},{"id":"minecraft:beetroot_soup","localizedName":"Beetroot Soup","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.beetroot_soup"},{"id":"minecraft:bell","localizedName":"Bell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bell"},{"id":"minecraft:birch_boat","localizedName":"Birch Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.birch_boat"},{"id":"minecraft:birch_button","localizedName":"Birch Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_button"},{"id":"minecraft:birch_door","localizedName":"Birch Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_door"},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence"},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence_gate"},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_leaves"},{"id":"minecraft:birch_log","localizedName":"Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_log"},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_planks"},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_pressure_plate"},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_sapling"},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.birch_sign"},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_slab"},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_stairs"},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_trapdoor"},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_wood"},{"id":"minecraft:black_banner","localizedName":"Black Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.black_banner"},{"id":"minecraft:black_bed","localizedName":"Black Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_bed"},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_carpet"},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete"},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete_powder"},{"id":"minecraft:black_dye","localizedName":"Black Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.black_dye"},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_glazed_terracotta"},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_shulker_box"},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass"},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass_pane"},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_terracotta"},{"id":"minecraft:black_wool","localizedName":"Black Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_wool"},{"id":"minecraft:blackstone","localizedName":"Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone"},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_slab"},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_stairs"},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_wall"},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blast_furnace"},{"id":"minecraft:blaze_powder","localizedName":"Blaze Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_powder"},{"id":"minecraft:blaze_rod","localizedName":"Blaze Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_rod"},{"id":"minecraft:blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_spawn_egg"},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.blue_banner"},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_bed"},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_carpet"},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete"},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete_powder"},{"id":"minecraft:blue_dye","localizedName":"Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blue_dye"},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_glazed_terracotta"},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_ice"},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_orchid"},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_shulker_box"},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass"},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass_pane"},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_terracotta"},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_wool"},{"id":"minecraft:bone","localizedName":"Bone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone"},{"id":"minecraft:bone_block","localizedName":"Bone Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bone_block"},{"id":"minecraft:bone_meal","localizedName":"Bone Meal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone_meal"},{"id":"minecraft:book","localizedName":"Book","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.book"},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bookshelf"},{"id":"minecraft:bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1,"unlocalizedName":"item.minecraft.bow"},{"id":"minecraft:bowl","localizedName":"Bowl","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bowl"},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral"},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_block"},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_fan"},{"id":"minecraft:bread","localizedName":"Bread","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bread"},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brewing_stand"},{"id":"minecraft:brick","localizedName":"Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brick"},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_slab"},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_stairs"},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_wall"},{"id":"minecraft:bricks","localizedName":"Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bricks"},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.brown_banner"},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_bed"},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_carpet"},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete"},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete_powder"},{"id":"minecraft:brown_dye","localizedName":"Brown Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brown_dye"},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_glazed_terracotta"},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom"},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom_block"},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_shulker_box"},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass"},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass_pane"},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_terracotta"},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_wool"},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral"},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_block"},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_fan"},{"id":"minecraft:bucket","localizedName":"Bucket","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.bucket"},{"id":"minecraft:cactus","localizedName":"Cactus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cactus"},{"id":"minecraft:cake","localizedName":"Cake","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cake"},{"id":"minecraft:campfire","localizedName":"Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.campfire"},{"id":"minecraft:carrot","localizedName":"Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.carrot"},{"id":"minecraft:carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1,"unlocalizedName":"item.minecraft.carrot_on_a_stick"},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cartography_table"},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.carved_pumpkin"},{"id":"minecraft:cat_spawn_egg","localizedName":"Cat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cat_spawn_egg"},{"id":"minecraft:cauldron","localizedName":"Cauldron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cauldron"},{"id":"minecraft:cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cave_spider_spawn_egg"},{"id":"minecraft:chain","localizedName":"Chain","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain"},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain_command_block"},{"id":"minecraft:chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_boots"},{"id":"minecraft:chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_chestplate"},{"id":"minecraft:chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_helmet"},{"id":"minecraft:chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_leggings"},{"id":"minecraft:charcoal","localizedName":"Charcoal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.charcoal"},{"id":"minecraft:chest","localizedName":"Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chest"},{"id":"minecraft:chest_minecart","localizedName":"Minecart with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.chest_minecart"},{"id":"minecraft:chicken","localizedName":"Raw Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken"},{"id":"minecraft:chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken_spawn_egg"},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chipped_anvil"},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_nether_bricks"},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_polished_blackstone"},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_quartz_block"},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_red_sandstone"},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_sandstone"},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_stone_bricks"},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_flower"},{"id":"minecraft:chorus_fruit","localizedName":"Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chorus_fruit"},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_plant"},{"id":"minecraft:clay","localizedName":"Clay","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.clay"},{"id":"minecraft:clay_ball","localizedName":"Clay Ball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clay_ball"},{"id":"minecraft:clock","localizedName":"Clock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clock"},{"id":"minecraft:coal","localizedName":"Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.coal"},{"id":"minecraft:coal_block","localizedName":"Block of Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_block"},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_ore"},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coarse_dirt"},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone"},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_slab"},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_stairs"},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_wall"},{"id":"minecraft:cobweb","localizedName":"Cobweb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobweb"},{"id":"minecraft:cocoa_beans","localizedName":"Cocoa Beans","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cocoa_beans"},{"id":"minecraft:cod","localizedName":"Raw Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod"},{"id":"minecraft:cod_bucket","localizedName":"Bucket of Cod","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.cod_bucket"},{"id":"minecraft:cod_spawn_egg","localizedName":"Cod Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod_spawn_egg"},{"id":"minecraft:command_block","localizedName":"Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.command_block"},{"id":"minecraft:command_block_minecart","localizedName":"Minecart with Command Block","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.command_block_minecart"},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.comparator"},{"id":"minecraft:compass","localizedName":"Compass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.compass"},{"id":"minecraft:composter","localizedName":"Composter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.composter"},{"id":"minecraft:conduit","localizedName":"Conduit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.conduit"},{"id":"minecraft:cooked_beef","localizedName":"Steak","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_beef"},{"id":"minecraft:cooked_chicken","localizedName":"Cooked Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_chicken"},{"id":"minecraft:cooked_cod","localizedName":"Cooked Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_cod"},{"id":"minecraft:cooked_mutton","localizedName":"Cooked Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_mutton"},{"id":"minecraft:cooked_porkchop","localizedName":"Cooked Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_porkchop"},{"id":"minecraft:cooked_rabbit","localizedName":"Cooked Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_rabbit"},{"id":"minecraft:cooked_salmon","localizedName":"Cooked Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_salmon"},{"id":"minecraft:cookie","localizedName":"Cookie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cookie"},{"id":"minecraft:cornflower","localizedName":"Cornflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cornflower"},{"id":"minecraft:cow_spawn_egg","localizedName":"Cow Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cow_spawn_egg"},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_nether_bricks"},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_polished_blackstone_bricks"},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_stone_bricks"},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crafting_table"},{"id":"minecraft:creeper_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.creeper_banner_pattern"},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.creeper_head"},{"id":"minecraft:creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.creeper_spawn_egg"},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_button"},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_door"},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence"},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence_gate"},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fungus"},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_hyphae"},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_nylium"},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_planks"},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_pressure_plate"},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_roots"},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_sign"},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_slab"},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stairs"},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stem"},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_trapdoor"},{"id":"minecraft:crossbow","localizedName":"Crossbow","maxDamage":326,"maxStackSize":1,"unlocalizedName":"item.minecraft.crossbow"},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crying_obsidian"},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone"},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone_slab"},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone"},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone_slab"},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.cyan_banner"},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_bed"},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_carpet"},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete"},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete_powder"},{"id":"minecraft:cyan_dye","localizedName":"Cyan Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cyan_dye"},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_glazed_terracotta"},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_shulker_box"},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass"},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass_pane"},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_terracotta"},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_wool"},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.damaged_anvil"},{"id":"minecraft:dandelion","localizedName":"Dandelion","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dandelion"},{"id":"minecraft:dark_oak_boat","localizedName":"Dark Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_boat"},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_button"},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_door"},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence"},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence_gate"},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_leaves"},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_log"},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_planks"},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_pressure_plate"},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_sapling"},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_sign"},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_slab"},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_stairs"},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_trapdoor"},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_wood"},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine"},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_slab"},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_stairs"},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.daylight_detector"},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral"},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_block"},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_fan"},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral"},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_block"},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_fan"},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bush"},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral"},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_block"},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_fan"},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral"},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_block"},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_fan"},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral"},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_block"},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_fan"},{"id":"minecraft:debug_stick","localizedName":"Debug Stick","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.debug_stick"},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.detector_rail"},{"id":"minecraft:diamond","localizedName":"Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.diamond"},{"id":"minecraft:diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_axe"},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_block"},{"id":"minecraft:diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_boots"},{"id":"minecraft:diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_chestplate"},{"id":"minecraft:diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_helmet"},{"id":"minecraft:diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_hoe"},{"id":"minecraft:diamond_horse_armor","localizedName":"Diamond Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_horse_armor"},{"id":"minecraft:diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_leggings"},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_ore"},{"id":"minecraft:diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_pickaxe"},{"id":"minecraft:diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_shovel"},{"id":"minecraft:diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_sword"},{"id":"minecraft:diorite","localizedName":"Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite"},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_slab"},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_stairs"},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_wall"},{"id":"minecraft:dirt","localizedName":"Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dirt"},{"id":"minecraft:dispenser","localizedName":"Dispenser","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dispenser"},{"id":"minecraft:dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dolphin_spawn_egg"},{"id":"minecraft:donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.donkey_spawn_egg"},{"id":"minecraft:dragon_breath","localizedName":"Dragon's Breath","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dragon_breath"},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_egg"},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_head"},{"id":"minecraft:dried_kelp","localizedName":"Dried Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dried_kelp"},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dried_kelp_block"},{"id":"minecraft:dropper","localizedName":"Dropper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dropper"},{"id":"minecraft:drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.drowned_spawn_egg"},{"id":"minecraft:egg","localizedName":"Egg","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.egg"},{"id":"minecraft:elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.elder_guardian_spawn_egg"},{"id":"minecraft:elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1,"unlocalizedName":"item.minecraft.elytra"},{"id":"minecraft:emerald","localizedName":"Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.emerald"},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_block"},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_ore"},{"id":"minecraft:enchanted_book","localizedName":"Enchanted Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.enchanted_book"},{"id":"minecraft:enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enchanted_golden_apple"},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.enchanting_table"},{"id":"minecraft:end_crystal","localizedName":"End Crystal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.end_crystal"},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_portal_frame"},{"id":"minecraft:end_rod","localizedName":"End Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_rod"},{"id":"minecraft:end_stone","localizedName":"End Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone"},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_slab"},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_stairs"},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_wall"},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_bricks"},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ender_chest"},{"id":"minecraft:ender_eye","localizedName":"Eye of Ender","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ender_eye"},{"id":"minecraft:ender_pearl","localizedName":"Ender Pearl","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.ender_pearl"},{"id":"minecraft:enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enderman_spawn_egg"},{"id":"minecraft:endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.endermite_spawn_egg"},{"id":"minecraft:evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.evoker_spawn_egg"},{"id":"minecraft:experience_bottle","localizedName":"Bottle o' Enchanting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.experience_bottle"},{"id":"minecraft:farmland","localizedName":"Farmland","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.farmland"},{"id":"minecraft:feather","localizedName":"Feather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.feather"},{"id":"minecraft:fermented_spider_eye","localizedName":"Fermented Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fermented_spider_eye"},{"id":"minecraft:fern","localizedName":"Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fern"},{"id":"minecraft:filled_map","localizedName":"Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.filled_map"},{"id":"minecraft:fire_charge","localizedName":"Fire Charge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fire_charge"},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral"},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_block"},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_fan"},{"id":"minecraft:firework_rocket","localizedName":"Firework Rocket","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_rocket"},{"id":"minecraft:firework_star","localizedName":"Firework Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_star"},{"id":"minecraft:fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.fishing_rod"},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fletching_table"},{"id":"minecraft:flint","localizedName":"Flint","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.flint"},{"id":"minecraft:flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.flint_and_steel"},{"id":"minecraft:flower_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.flower_banner_pattern"},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flower_pot"},{"id":"minecraft:fox_spawn_egg","localizedName":"Fox Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fox_spawn_egg"},{"id":"minecraft:furnace","localizedName":"Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.furnace"},{"id":"minecraft:furnace_minecart","localizedName":"Minecart with Furnace","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.furnace_minecart"},{"id":"minecraft:ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_spawn_egg"},{"id":"minecraft:ghast_tear","localizedName":"Ghast Tear","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_tear"},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gilded_blackstone"},{"id":"minecraft:glass","localizedName":"Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass"},{"id":"minecraft:glass_bottle","localizedName":"Glass Bottle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glass_bottle"},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass_pane"},{"id":"minecraft:glistering_melon_slice","localizedName":"Glistering Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glistering_melon_slice"},{"id":"minecraft:globe_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.globe_banner_pattern"},{"id":"minecraft:glowstone","localizedName":"Glowstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glowstone"},{"id":"minecraft:glowstone_dust","localizedName":"Glowstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glowstone_dust"},{"id":"minecraft:gold_block","localizedName":"Block of Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_block"},{"id":"minecraft:gold_ingot","localizedName":"Gold Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_ingot"},{"id":"minecraft:gold_nugget","localizedName":"Gold Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_nugget"},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_ore"},{"id":"minecraft:golden_apple","localizedName":"Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_apple"},{"id":"minecraft:golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_axe"},{"id":"minecraft:golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_boots"},{"id":"minecraft:golden_carrot","localizedName":"Golden Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_carrot"},{"id":"minecraft:golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_chestplate"},{"id":"minecraft:golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_helmet"},{"id":"minecraft:golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_hoe"},{"id":"minecraft:golden_horse_armor","localizedName":"Golden Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_horse_armor"},{"id":"minecraft:golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_leggings"},{"id":"minecraft:golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_pickaxe"},{"id":"minecraft:golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_shovel"},{"id":"minecraft:golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_sword"},{"id":"minecraft:granite","localizedName":"Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite"},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_slab"},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_stairs"},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_wall"},{"id":"minecraft:grass","localizedName":"Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass"},{"id":"minecraft:grass_block","localizedName":"Grass Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass_block"},{"id":"minecraft:grass_path","localizedName":"Grass Path","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass_path"},{"id":"minecraft:gravel","localizedName":"Gravel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gravel"},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.gray_banner"},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_bed"},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_carpet"},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete"},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete_powder"},{"id":"minecraft:gray_dye","localizedName":"Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gray_dye"},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_glazed_terracotta"},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_shulker_box"},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass"},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass_pane"},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_terracotta"},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_wool"},{"id":"minecraft:green_banner","localizedName":"Green Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.green_banner"},{"id":"minecraft:green_bed","localizedName":"Green Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_bed"},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_carpet"},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete"},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete_powder"},{"id":"minecraft:green_dye","localizedName":"Green Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.green_dye"},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_glazed_terracotta"},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_shulker_box"},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass"},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass_pane"},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_terracotta"},{"id":"minecraft:green_wool","localizedName":"Green Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_wool"},{"id":"minecraft:grindstone","localizedName":"Grindstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grindstone"},{"id":"minecraft:guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.guardian_spawn_egg"},{"id":"minecraft:gunpowder","localizedName":"Gunpowder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gunpowder"},{"id":"minecraft:hay_block","localizedName":"Hay Bale","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hay_block"},{"id":"minecraft:heart_of_the_sea","localizedName":"Heart of the Sea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.heart_of_the_sea"},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate"},{"id":"minecraft:hoglin_spawn_egg","localizedName":"Hoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.hoglin_spawn_egg"},{"id":"minecraft:honey_block","localizedName":"Honey Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honey_block"},{"id":"minecraft:honey_bottle","localizedName":"Honey Bottle","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.honey_bottle"},{"id":"minecraft:honeycomb","localizedName":"Honeycomb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.honeycomb"},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honeycomb_block"},{"id":"minecraft:hopper","localizedName":"Hopper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hopper"},{"id":"minecraft:hopper_minecart","localizedName":"Minecart with Hopper","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.hopper_minecart"},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral"},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_block"},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_fan"},{"id":"minecraft:horse_spawn_egg","localizedName":"Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.horse_spawn_egg"},{"id":"minecraft:husk_spawn_egg","localizedName":"Husk Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.husk_spawn_egg"},{"id":"minecraft:ice","localizedName":"Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ice"},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks"},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cobblestone"},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cracked_stone_bricks"},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_mossy_stone_bricks"},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone"},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone_bricks"},{"id":"minecraft:ink_sac","localizedName":"Ink Sac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ink_sac"},{"id":"minecraft:iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_axe"},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_bars"},{"id":"minecraft:iron_block","localizedName":"Block of Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_block"},{"id":"minecraft:iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_boots"},{"id":"minecraft:iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_chestplate"},{"id":"minecraft:iron_door","localizedName":"Iron Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_door"},{"id":"minecraft:iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_helmet"},{"id":"minecraft:iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_hoe"},{"id":"minecraft:iron_horse_armor","localizedName":"Iron Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_horse_armor"},{"id":"minecraft:iron_ingot","localizedName":"Iron Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_ingot"},{"id":"minecraft:iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_leggings"},{"id":"minecraft:iron_nugget","localizedName":"Iron Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_nugget"},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_ore"},{"id":"minecraft:iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_pickaxe"},{"id":"minecraft:iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_shovel"},{"id":"minecraft:iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_sword"},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_trapdoor"},{"id":"minecraft:item_frame","localizedName":"Item Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.item_frame"},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o'Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jack_o_lantern"},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jigsaw"},{"id":"minecraft:jukebox","localizedName":"Jukebox","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jukebox"},{"id":"minecraft:jungle_boat","localizedName":"Jungle Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_boat"},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_button"},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_door"},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence"},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence_gate"},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_leaves"},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_log"},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_planks"},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_pressure_plate"},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_sapling"},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_sign"},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_slab"},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_stairs"},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_trapdoor"},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_wood"},{"id":"minecraft:kelp","localizedName":"Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.kelp"},{"id":"minecraft:knowledge_book","localizedName":"Knowledge Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.knowledge_book"},{"id":"minecraft:ladder","localizedName":"Ladder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ladder"},{"id":"minecraft:lantern","localizedName":"Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lantern"},{"id":"minecraft:lapis_block","localizedName":"Lapis Lazuli Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_block"},{"id":"minecraft:lapis_lazuli","localizedName":"Lapis Lazuli","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lapis_lazuli"},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_ore"},{"id":"minecraft:large_fern","localizedName":"Large Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.large_fern"},{"id":"minecraft:lava_bucket","localizedName":"Lava Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lava_bucket"},{"id":"minecraft:lead","localizedName":"Lead","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lead"},{"id":"minecraft:leather","localizedName":"Leather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.leather"},{"id":"minecraft:leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_boots"},{"id":"minecraft:leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_chestplate"},{"id":"minecraft:leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_helmet"},{"id":"minecraft:leather_horse_armor","localizedName":"Leather Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_horse_armor"},{"id":"minecraft:leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_leggings"},{"id":"minecraft:lectern","localizedName":"Lectern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lectern"},{"id":"minecraft:lever","localizedName":"Lever","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lever"},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_blue_banner"},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_bed"},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_carpet"},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete"},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete_powder"},{"id":"minecraft:light_blue_dye","localizedName":"Light Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_blue_dye"},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_glazed_terracotta"},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_shulker_box"},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass"},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass_pane"},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_terracotta"},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_wool"},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_gray_banner"},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_bed"},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_carpet"},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete"},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete_powder"},{"id":"minecraft:light_gray_dye","localizedName":"Light Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_gray_dye"},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_glazed_terracotta"},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_shulker_box"},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass"},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass_pane"},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_terracotta"},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_wool"},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_weighted_pressure_plate"},{"id":"minecraft:lilac","localizedName":"Lilac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lilac"},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_of_the_valley"},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_pad"},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.lime_banner"},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_bed"},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_carpet"},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete"},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete_powder"},{"id":"minecraft:lime_dye","localizedName":"Lime Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lime_dye"},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_glazed_terracotta"},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_shulker_box"},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass"},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass_pane"},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_terracotta"},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_wool"},{"id":"minecraft:lingering_potion","localizedName":"Lingering Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lingering_potion.effect.water"},{"id":"minecraft:llama_spawn_egg","localizedName":"Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.llama_spawn_egg"},{"id":"minecraft:lodestone","localizedName":"Lodestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lodestone"},{"id":"minecraft:loom","localizedName":"Loom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.loom"},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.magenta_banner"},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_bed"},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_carpet"},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete"},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete_powder"},{"id":"minecraft:magenta_dye","localizedName":"Magenta Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magenta_dye"},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_glazed_terracotta"},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_shulker_box"},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass"},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass_pane"},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_terracotta"},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_wool"},{"id":"minecraft:magma_block","localizedName":"Magma Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magma_block"},{"id":"minecraft:magma_cream","localizedName":"Magma Cream","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cream"},{"id":"minecraft:magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cube_spawn_egg"},{"id":"minecraft:map","localizedName":"Empty Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.map"},{"id":"minecraft:melon","localizedName":"Melon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.melon"},{"id":"minecraft:melon_seeds","localizedName":"Melon Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_seeds"},{"id":"minecraft:melon_slice","localizedName":"Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_slice"},{"id":"minecraft:milk_bucket","localizedName":"Milk Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.milk_bucket"},{"id":"minecraft:minecart","localizedName":"Minecart","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.minecart"},{"id":"minecraft:mojang_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mojang_banner_pattern"},{"id":"minecraft:mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mooshroom_spawn_egg"},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone"},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_slab"},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_stairs"},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_wall"},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_slab"},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_stairs"},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_wall"},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_bricks"},{"id":"minecraft:mule_spawn_egg","localizedName":"Mule Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mule_spawn_egg"},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mushroom_stem"},{"id":"minecraft:mushroom_stew","localizedName":"Mushroom Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mushroom_stew"},{"id":"minecraft:music_disc_11","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_11"},{"id":"minecraft:music_disc_13","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_13"},{"id":"minecraft:music_disc_blocks","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_blocks"},{"id":"minecraft:music_disc_cat","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_cat"},{"id":"minecraft:music_disc_chirp","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_chirp"},{"id":"minecraft:music_disc_far","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_far"},{"id":"minecraft:music_disc_mall","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mall"},{"id":"minecraft:music_disc_mellohi","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mellohi"},{"id":"minecraft:music_disc_pigstep","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_pigstep"},{"id":"minecraft:music_disc_stal","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_stal"},{"id":"minecraft:music_disc_strad","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_strad"},{"id":"minecraft:music_disc_wait","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_wait"},{"id":"minecraft:music_disc_ward","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_ward"},{"id":"minecraft:mutton","localizedName":"Raw Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mutton"},{"id":"minecraft:mycelium","localizedName":"Mycelium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mycelium"},{"id":"minecraft:name_tag","localizedName":"Name Tag","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.name_tag"},{"id":"minecraft:nautilus_shell","localizedName":"Nautilus Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nautilus_shell"},{"id":"minecraft:nether_brick","localizedName":"Nether Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_brick"},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_fence"},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_slab"},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_stairs"},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_wall"},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_bricks"},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_gold_ore"},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_quartz_ore"},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_sprouts"},{"id":"minecraft:nether_star","localizedName":"Nether Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_star"},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_wart"},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_wart_block"},{"id":"minecraft:netherite_axe","localizedName":"Netherite Axe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_axe"},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherite_block"},{"id":"minecraft:netherite_boots","localizedName":"Netherite Boots","maxDamage":481,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_boots"},{"id":"minecraft:netherite_chestplate","localizedName":"Netherite Chestplate","maxDamage":592,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_chestplate"},{"id":"minecraft:netherite_helmet","localizedName":"Netherite Helmet","maxDamage":407,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_helmet"},{"id":"minecraft:netherite_hoe","localizedName":"Netherite Hoe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_hoe"},{"id":"minecraft:netherite_ingot","localizedName":"Netherite Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_ingot"},{"id":"minecraft:netherite_leggings","localizedName":"Netherite Leggings","maxDamage":555,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_leggings"},{"id":"minecraft:netherite_pickaxe","localizedName":"Netherite Pickaxe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_pickaxe"},{"id":"minecraft:netherite_scrap","localizedName":"Netherite Scrap","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_scrap"},{"id":"minecraft:netherite_shovel","localizedName":"Netherite Shovel","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_shovel"},{"id":"minecraft:netherite_sword","localizedName":"Netherite Sword","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_sword"},{"id":"minecraft:netherrack","localizedName":"Netherrack","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherrack"},{"id":"minecraft:note_block","localizedName":"Note Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.note_block"},{"id":"minecraft:oak_boat","localizedName":"Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.oak_boat"},{"id":"minecraft:oak_button","localizedName":"Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_button"},{"id":"minecraft:oak_door","localizedName":"Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_door"},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence"},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence_gate"},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_leaves"},{"id":"minecraft:oak_log","localizedName":"Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_log"},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_planks"},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_pressure_plate"},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_sapling"},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.oak_sign"},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_slab"},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_stairs"},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_trapdoor"},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_wood"},{"id":"minecraft:observer","localizedName":"Observer","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.observer"},{"id":"minecraft:obsidian","localizedName":"Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.obsidian"},{"id":"minecraft:ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ocelot_spawn_egg"},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.orange_banner"},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_bed"},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_carpet"},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete"},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete_powder"},{"id":"minecraft:orange_dye","localizedName":"Orange Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.orange_dye"},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_glazed_terracotta"},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_shulker_box"},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass"},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass_pane"},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_terracotta"},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_tulip"},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_wool"},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxeye_daisy"},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.packed_ice"},{"id":"minecraft:painting","localizedName":"Painting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.painting"},{"id":"minecraft:panda_spawn_egg","localizedName":"Panda Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.panda_spawn_egg"},{"id":"minecraft:paper","localizedName":"Paper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.paper"},{"id":"minecraft:parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.parrot_spawn_egg"},{"id":"minecraft:peony","localizedName":"Peony","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.peony"},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.petrified_oak_slab"},{"id":"minecraft:phantom_membrane","localizedName":"Phantom Membrane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_membrane"},{"id":"minecraft:phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_spawn_egg"},{"id":"minecraft:pig_spawn_egg","localizedName":"Pig Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pig_spawn_egg"},{"id":"minecraft:piglin_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.piglin_banner_pattern"},{"id":"minecraft:piglin_brute_spawn_egg","localizedName":"Piglin Brute Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_brute_spawn_egg"},{"id":"minecraft:piglin_spawn_egg","localizedName":"Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_spawn_egg"},{"id":"minecraft:pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pillager_spawn_egg"},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.pink_banner"},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_bed"},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_carpet"},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete"},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete_powder"},{"id":"minecraft:pink_dye","localizedName":"Pink Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pink_dye"},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_glazed_terracotta"},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_shulker_box"},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass"},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass_pane"},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_terracotta"},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_tulip"},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_wool"},{"id":"minecraft:piston","localizedName":"Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.piston"},{"id":"minecraft:player_head","localizedName":"Player Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.player_head"},{"id":"minecraft:podzol","localizedName":"Podzol","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.podzol"},{"id":"minecraft:poisonous_potato","localizedName":"Poisonous Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.poisonous_potato"},{"id":"minecraft:polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.polar_bear_spawn_egg"},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite"},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_slab"},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_stairs"},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_basalt"},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone"},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_slab"},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_stairs"},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_wall"},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_bricks"},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_button"},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_pressure_plate"},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_slab"},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_stairs"},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_wall"},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite"},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_slab"},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_stairs"},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite"},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_slab"},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_stairs"},{"id":"minecraft:popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.popped_chorus_fruit"},{"id":"minecraft:poppy","localizedName":"Poppy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.poppy"},{"id":"minecraft:porkchop","localizedName":"Raw Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.porkchop"},{"id":"minecraft:potato","localizedName":"Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.potato"},{"id":"minecraft:potion","localizedName":"Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.potion.effect.water"},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.powered_rail"},{"id":"minecraft:prismarine","localizedName":"Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine"},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_slab"},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_stairs"},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_bricks"},{"id":"minecraft:prismarine_crystals","localizedName":"Prismarine Crystals","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_crystals"},{"id":"minecraft:prismarine_shard","localizedName":"Prismarine Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_shard"},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_slab"},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_stairs"},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_wall"},{"id":"minecraft:pufferfish","localizedName":"Pufferfish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish"},{"id":"minecraft:pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.pufferfish_bucket"},{"id":"minecraft:pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish_spawn_egg"},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pumpkin"},{"id":"minecraft:pumpkin_pie","localizedName":"Pumpkin Pie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_pie"},{"id":"minecraft:pumpkin_seeds","localizedName":"Pumpkin Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_seeds"},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.purple_banner"},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_bed"},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_carpet"},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete"},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete_powder"},{"id":"minecraft:purple_dye","localizedName":"Purple Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.purple_dye"},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_glazed_terracotta"},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_shulker_box"},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass"},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass_pane"},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_terracotta"},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_wool"},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_block"},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_pillar"},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_slab"},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_stairs"},{"id":"minecraft:quartz","localizedName":"Nether Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.quartz"},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_block"},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_bricks"},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_pillar"},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_slab"},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_stairs"},{"id":"minecraft:rabbit","localizedName":"Raw Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit"},{"id":"minecraft:rabbit_foot","localizedName":"Rabbit's Foot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_foot"},{"id":"minecraft:rabbit_hide","localizedName":"Rabbit Hide","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_hide"},{"id":"minecraft:rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_spawn_egg"},{"id":"minecraft:rabbit_stew","localizedName":"Rabbit Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.rabbit_stew"},{"id":"minecraft:rail","localizedName":"Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rail"},{"id":"minecraft:ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ravager_spawn_egg"},{"id":"minecraft:red_banner","localizedName":"Red Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.red_banner"},{"id":"minecraft:red_bed","localizedName":"Red Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_bed"},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_carpet"},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete"},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete_powder"},{"id":"minecraft:red_dye","localizedName":"Red Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.red_dye"},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_glazed_terracotta"},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom"},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom_block"},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_slab"},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_stairs"},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_wall"},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_bricks"},{"id":"minecraft:red_sand","localizedName":"Red Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sand"},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone"},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_slab"},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_stairs"},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_wall"},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_shulker_box"},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass"},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass_pane"},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_terracotta"},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_tulip"},{"id":"minecraft:red_wool","localizedName":"Red Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_wool"},{"id":"minecraft:redstone","localizedName":"Redstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.redstone"},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_block"},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_lamp"},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_ore"},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_torch"},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeater"},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeating_command_block"},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.respawn_anchor"},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rose_bush"},{"id":"minecraft:rotten_flesh","localizedName":"Rotten Flesh","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rotten_flesh"},{"id":"minecraft:saddle","localizedName":"Saddle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.saddle"},{"id":"minecraft:salmon","localizedName":"Raw Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon"},{"id":"minecraft:salmon_bucket","localizedName":"Bucket of Salmon","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.salmon_bucket"},{"id":"minecraft:salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon_spawn_egg"},{"id":"minecraft:sand","localizedName":"Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sand"},{"id":"minecraft:sandstone","localizedName":"Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone"},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_slab"},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_stairs"},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_wall"},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.scaffolding"},{"id":"minecraft:scute","localizedName":"Scute","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.scute"},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_lantern"},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_pickle"},{"id":"minecraft:seagrass","localizedName":"Seagrass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.seagrass"},{"id":"minecraft:shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1,"unlocalizedName":"item.minecraft.shears"},{"id":"minecraft:sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sheep_spawn_egg"},{"id":"minecraft:shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1,"unlocalizedName":"item.minecraft.shield"},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.shroomlight"},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.shulker_box"},{"id":"minecraft:shulker_shell","localizedName":"Shulker Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_shell"},{"id":"minecraft:shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_spawn_egg"},{"id":"minecraft:silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.silverfish_spawn_egg"},{"id":"minecraft:skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg"},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.skeleton_skull"},{"id":"minecraft:skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_spawn_egg"},{"id":"minecraft:skull_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.skull_banner_pattern"},{"id":"minecraft:slime_ball","localizedName":"Slimeball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_ball"},{"id":"minecraft:slime_block","localizedName":"Slime Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.slime_block"},{"id":"minecraft:slime_spawn_egg","localizedName":"Slime Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_spawn_egg"},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smithing_table"},{"id":"minecraft:smoker","localizedName":"Smoker","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smoker"},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz"},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_slab"},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_stairs"},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone"},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_slab"},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs"},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone"},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_slab"},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_stairs"},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone"},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone_slab"},{"id":"minecraft:snow","localizedName":"Snow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow"},{"id":"minecraft:snow_block","localizedName":"Snow Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow_block"},{"id":"minecraft:snowball","localizedName":"Snowball","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.snowball"},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_campfire"},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_lantern"},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_sand"},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_soil"},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_torch"},{"id":"minecraft:spawner","localizedName":"Spawner","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spawner"},{"id":"minecraft:spectral_arrow","localizedName":"Spectral Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spectral_arrow"},{"id":"minecraft:spider_eye","localizedName":"Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_eye"},{"id":"minecraft:spider_spawn_egg","localizedName":"Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_spawn_egg"},{"id":"minecraft:splash_potion","localizedName":"Splash Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.splash_potion.effect.water"},{"id":"minecraft:sponge","localizedName":"Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sponge"},{"id":"minecraft:spruce_boat","localizedName":"Spruce Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_boat"},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_button"},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_door"},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence"},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence_gate"},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_leaves"},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_log"},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_planks"},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_pressure_plate"},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_sapling"},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_sign"},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_slab"},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_stairs"},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_trapdoor"},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_wood"},{"id":"minecraft:squid_spawn_egg","localizedName":"Squid Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.squid_spawn_egg"},{"id":"minecraft:stick","localizedName":"Stick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stick"},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sticky_piston"},{"id":"minecraft:stone","localizedName":"Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone"},{"id":"minecraft:stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_axe"},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_slab"},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_stairs"},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_wall"},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_bricks"},{"id":"minecraft:stone_button","localizedName":"Stone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_button"},{"id":"minecraft:stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_hoe"},{"id":"minecraft:stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_pickaxe"},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_pressure_plate"},{"id":"minecraft:stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_shovel"},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_slab"},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_stairs"},{"id":"minecraft:stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_sword"},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stonecutter"},{"id":"minecraft:stray_spawn_egg","localizedName":"Stray Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stray_spawn_egg"},{"id":"minecraft:strider_spawn_egg","localizedName":"Strider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.strider_spawn_egg"},{"id":"minecraft:string","localizedName":"String","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.string"},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_log"},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_wood"},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_log"},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_wood"},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_hyphae"},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_stem"},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_log"},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_wood"},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_log"},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_wood"},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_log"},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_wood"},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_log"},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_wood"},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_hyphae"},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_stem"},{"id":"minecraft:structure_block","localizedName":"Structure Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_block"},{"id":"minecraft:structure_void","localizedName":"Structure Void","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_void"},{"id":"minecraft:sugar","localizedName":"Sugar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sugar"},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sugar_cane"},{"id":"minecraft:sunflower","localizedName":"Sunflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sunflower"},{"id":"minecraft:suspicious_stew","localizedName":"Suspicious Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.suspicious_stew"},{"id":"minecraft:sweet_berries","localizedName":"Sweet Berries","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sweet_berries"},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tall_grass"},{"id":"minecraft:target","localizedName":"Target","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.target"},{"id":"minecraft:terracotta","localizedName":"Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.terracotta"},{"id":"minecraft:tipped_arrow","localizedName":"Arrow of Poison","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tipped_arrow.effect.poison"},{"id":"minecraft:tnt","localizedName":"TNT","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tnt"},{"id":"minecraft:tnt_minecart","localizedName":"Minecart with TNT","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tnt_minecart"},{"id":"minecraft:torch","localizedName":"Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.torch"},{"id":"minecraft:totem_of_undying","localizedName":"Totem of Undying","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.totem_of_undying"},{"id":"minecraft:trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.trader_llama_spawn_egg"},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.trapped_chest"},{"id":"minecraft:trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.trident"},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tripwire_hook"},{"id":"minecraft:tropical_fish","localizedName":"Tropical Fish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish"},{"id":"minecraft:tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tropical_fish_bucket"},{"id":"minecraft:tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish_spawn_egg"},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral"},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_block"},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_fan"},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.turtle_egg"},{"id":"minecraft:turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1,"unlocalizedName":"item.minecraft.turtle_helmet"},{"id":"minecraft:turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_spawn_egg"},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.twisting_vines"},{"id":"minecraft:vex_spawn_egg","localizedName":"Vex Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vex_spawn_egg"},{"id":"minecraft:villager_spawn_egg","localizedName":"Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.villager_spawn_egg"},{"id":"minecraft:vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vindicator_spawn_egg"},{"id":"minecraft:vine","localizedName":"Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.vine"},{"id":"minecraft:wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wandering_trader_spawn_egg"},{"id":"minecraft:warped_button","localizedName":"Warped Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_button"},{"id":"minecraft:warped_door","localizedName":"Warped Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_door"},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence"},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence_gate"},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fungus"},{"id":"minecraft:warped_fungus_on_a_stick","localizedName":"Warped Fungus on a Stick","maxDamage":100,"maxStackSize":1,"unlocalizedName":"item.minecraft.warped_fungus_on_a_stick"},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_hyphae"},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_nylium"},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_planks"},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_pressure_plate"},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_roots"},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.warped_sign"},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_slab"},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stairs"},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stem"},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_trapdoor"},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_wart_block"},{"id":"minecraft:water_bucket","localizedName":"Water Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.water_bucket"},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weeping_vines"},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wet_sponge"},{"id":"minecraft:wheat","localizedName":"Wheat","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat"},{"id":"minecraft:wheat_seeds","localizedName":"Wheat Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat_seeds"},{"id":"minecraft:white_banner","localizedName":"White Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.white_banner"},{"id":"minecraft:white_bed","localizedName":"White Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_bed"},{"id":"minecraft:white_carpet","localizedName":"White Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_carpet"},{"id":"minecraft:white_concrete","localizedName":"White Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete"},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete_powder"},{"id":"minecraft:white_dye","localizedName":"White Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.white_dye"},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_glazed_terracotta"},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_shulker_box"},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass"},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass_pane"},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_terracotta"},{"id":"minecraft:white_tulip","localizedName":"White Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_tulip"},{"id":"minecraft:white_wool","localizedName":"White Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_wool"},{"id":"minecraft:witch_spawn_egg","localizedName":"Witch Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.witch_spawn_egg"},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_rose"},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_skeleton_skull"},{"id":"minecraft:wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg"},{"id":"minecraft:wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wolf_spawn_egg"},{"id":"minecraft:wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_axe"},{"id":"minecraft:wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_hoe"},{"id":"minecraft:wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_pickaxe"},{"id":"minecraft:wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_shovel"},{"id":"minecraft:wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_sword"},{"id":"minecraft:writable_book","localizedName":"Book and Quill","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.writable_book"},{"id":"minecraft:written_book","localizedName":"Written Book","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.written_book"},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.yellow_banner"},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_bed"},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_carpet"},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete"},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete_powder"},{"id":"minecraft:yellow_dye","localizedName":"Yellow Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.yellow_dye"},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_glazed_terracotta"},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_shulker_box"},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass"},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass_pane"},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_terracotta"},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_wool"},{"id":"minecraft:zoglin_spawn_egg","localizedName":"Zoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zoglin_spawn_egg"},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.zombie_head"},{"id":"minecraft:zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_horse_spawn_egg"},{"id":"minecraft:zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_spawn_egg"},{"id":"minecraft:zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_villager_spawn_egg"},{"id":"minecraft:zombified_piglin_spawn_egg","localizedName":"Zombified Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombified_piglin_spawn_egg"}] \ No newline at end of file diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.117.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.117.json deleted file mode 100644 index ed74d4d09..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.117.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_boat","localizedName":"Acacia Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_boat"},{"id":"minecraft:acacia_button","localizedName":"Acacia Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_button"},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_door"},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence"},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence_gate"},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_leaves"},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_log"},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_planks"},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_pressure_plate"},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_sapling"},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_sign"},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_slab"},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_stairs"},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_trapdoor"},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_wood"},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.activator_rail"},{"id":"minecraft:air","localizedName":"Air","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.air"},{"id":"minecraft:allium","localizedName":"Allium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.allium"},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_block"},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_cluster"},{"id":"minecraft:amethyst_shard","localizedName":"Amethyst Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.amethyst_shard"},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ancient_debris"},{"id":"minecraft:andesite","localizedName":"Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite"},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_slab"},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_stairs"},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_wall"},{"id":"minecraft:anvil","localizedName":"Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.anvil"},{"id":"minecraft:apple","localizedName":"Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.apple"},{"id":"minecraft:armor_stand","localizedName":"Armor Stand","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.armor_stand"},{"id":"minecraft:arrow","localizedName":"Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.arrow"},{"id":"minecraft:axolotl_bucket","localizedName":"Bucket of Axolotl","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.axolotl_bucket"},{"id":"minecraft:axolotl_spawn_egg","localizedName":"Axolotl Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.axolotl_spawn_egg"},{"id":"minecraft:azalea","localizedName":"Azalea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azalea"},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azalea_leaves"},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azure_bluet"},{"id":"minecraft:baked_potato","localizedName":"Baked Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.baked_potato"},{"id":"minecraft:bamboo","localizedName":"Bamboo","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo"},{"id":"minecraft:barrel","localizedName":"Barrel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrel"},{"id":"minecraft:barrier","localizedName":"Barrier","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrier"},{"id":"minecraft:basalt","localizedName":"Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.basalt"},{"id":"minecraft:bat_spawn_egg","localizedName":"Bat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bat_spawn_egg"},{"id":"minecraft:beacon","localizedName":"Beacon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beacon"},{"id":"minecraft:bedrock","localizedName":"Bedrock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bedrock"},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bee_nest"},{"id":"minecraft:bee_spawn_egg","localizedName":"Bee Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bee_spawn_egg"},{"id":"minecraft:beef","localizedName":"Raw Beef","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beef"},{"id":"minecraft:beehive","localizedName":"Beehive","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beehive"},{"id":"minecraft:beetroot","localizedName":"Beetroot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot"},{"id":"minecraft:beetroot_seeds","localizedName":"Beetroot Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot_seeds"},{"id":"minecraft:beetroot_soup","localizedName":"Beetroot Soup","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.beetroot_soup"},{"id":"minecraft:bell","localizedName":"Bell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bell"},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.big_dripleaf"},{"id":"minecraft:birch_boat","localizedName":"Birch Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.birch_boat"},{"id":"minecraft:birch_button","localizedName":"Birch Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_button"},{"id":"minecraft:birch_door","localizedName":"Birch Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_door"},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence"},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence_gate"},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_leaves"},{"id":"minecraft:birch_log","localizedName":"Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_log"},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_planks"},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_pressure_plate"},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_sapling"},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.birch_sign"},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_slab"},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_stairs"},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_trapdoor"},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_wood"},{"id":"minecraft:black_banner","localizedName":"Black Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.black_banner"},{"id":"minecraft:black_bed","localizedName":"Black Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_bed"},{"id":"minecraft:black_candle","localizedName":"Black Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_candle"},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_carpet"},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete"},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete_powder"},{"id":"minecraft:black_dye","localizedName":"Black Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.black_dye"},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_glazed_terracotta"},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_shulker_box"},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass"},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass_pane"},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_terracotta"},{"id":"minecraft:black_wool","localizedName":"Black Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_wool"},{"id":"minecraft:blackstone","localizedName":"Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone"},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_slab"},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_stairs"},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_wall"},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blast_furnace"},{"id":"minecraft:blaze_powder","localizedName":"Blaze Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_powder"},{"id":"minecraft:blaze_rod","localizedName":"Blaze Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_rod"},{"id":"minecraft:blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_spawn_egg"},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.blue_banner"},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_bed"},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_candle"},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_carpet"},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete"},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete_powder"},{"id":"minecraft:blue_dye","localizedName":"Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blue_dye"},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_glazed_terracotta"},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_ice"},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_orchid"},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_shulker_box"},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass"},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass_pane"},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_terracotta"},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_wool"},{"id":"minecraft:bone","localizedName":"Bone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone"},{"id":"minecraft:bone_block","localizedName":"Bone Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bone_block"},{"id":"minecraft:bone_meal","localizedName":"Bone Meal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone_meal"},{"id":"minecraft:book","localizedName":"Book","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.book"},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bookshelf"},{"id":"minecraft:bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1,"unlocalizedName":"item.minecraft.bow"},{"id":"minecraft:bowl","localizedName":"Bowl","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bowl"},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral"},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_block"},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_fan"},{"id":"minecraft:bread","localizedName":"Bread","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bread"},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brewing_stand"},{"id":"minecraft:brick","localizedName":"Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brick"},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_slab"},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_stairs"},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_wall"},{"id":"minecraft:bricks","localizedName":"Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bricks"},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.brown_banner"},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_bed"},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_candle"},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_carpet"},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete"},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete_powder"},{"id":"minecraft:brown_dye","localizedName":"Brown Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brown_dye"},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_glazed_terracotta"},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom"},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom_block"},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_shulker_box"},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass"},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass_pane"},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_terracotta"},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_wool"},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral"},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_block"},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_fan"},{"id":"minecraft:bucket","localizedName":"Bucket","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.bucket"},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.budding_amethyst"},{"id":"minecraft:bundle","localizedName":"Bundle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.bundle"},{"id":"minecraft:cactus","localizedName":"Cactus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cactus"},{"id":"minecraft:cake","localizedName":"Cake","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cake"},{"id":"minecraft:calcite","localizedName":"Calcite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.calcite"},{"id":"minecraft:campfire","localizedName":"Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.campfire"},{"id":"minecraft:candle","localizedName":"Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.candle"},{"id":"minecraft:carrot","localizedName":"Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.carrot"},{"id":"minecraft:carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1,"unlocalizedName":"item.minecraft.carrot_on_a_stick"},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cartography_table"},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.carved_pumpkin"},{"id":"minecraft:cat_spawn_egg","localizedName":"Cat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cat_spawn_egg"},{"id":"minecraft:cauldron","localizedName":"Cauldron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cauldron"},{"id":"minecraft:cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cave_spider_spawn_egg"},{"id":"minecraft:chain","localizedName":"Chain","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain"},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain_command_block"},{"id":"minecraft:chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_boots"},{"id":"minecraft:chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_chestplate"},{"id":"minecraft:chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_helmet"},{"id":"minecraft:chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_leggings"},{"id":"minecraft:charcoal","localizedName":"Charcoal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.charcoal"},{"id":"minecraft:chest","localizedName":"Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chest"},{"id":"minecraft:chest_minecart","localizedName":"Minecart with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.chest_minecart"},{"id":"minecraft:chicken","localizedName":"Raw Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken"},{"id":"minecraft:chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken_spawn_egg"},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chipped_anvil"},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_deepslate"},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_nether_bricks"},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_polished_blackstone"},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_quartz_block"},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_red_sandstone"},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_sandstone"},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_stone_bricks"},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_flower"},{"id":"minecraft:chorus_fruit","localizedName":"Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chorus_fruit"},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_plant"},{"id":"minecraft:clay","localizedName":"Clay","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.clay"},{"id":"minecraft:clay_ball","localizedName":"Clay Ball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clay_ball"},{"id":"minecraft:clock","localizedName":"Clock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clock"},{"id":"minecraft:coal","localizedName":"Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.coal"},{"id":"minecraft:coal_block","localizedName":"Block of Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_block"},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_ore"},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coarse_dirt"},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate"},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_slab"},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_stairs"},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_wall"},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone"},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_slab"},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_stairs"},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_wall"},{"id":"minecraft:cobweb","localizedName":"Cobweb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobweb"},{"id":"minecraft:cocoa_beans","localizedName":"Cocoa Beans","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cocoa_beans"},{"id":"minecraft:cod","localizedName":"Raw Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod"},{"id":"minecraft:cod_bucket","localizedName":"Bucket of Cod","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.cod_bucket"},{"id":"minecraft:cod_spawn_egg","localizedName":"Cod Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod_spawn_egg"},{"id":"minecraft:command_block","localizedName":"Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.command_block"},{"id":"minecraft:command_block_minecart","localizedName":"Minecart with Command Block","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.command_block_minecart"},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.comparator"},{"id":"minecraft:compass","localizedName":"Compass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.compass"},{"id":"minecraft:composter","localizedName":"Composter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.composter"},{"id":"minecraft:conduit","localizedName":"Conduit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.conduit"},{"id":"minecraft:cooked_beef","localizedName":"Steak","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_beef"},{"id":"minecraft:cooked_chicken","localizedName":"Cooked Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_chicken"},{"id":"minecraft:cooked_cod","localizedName":"Cooked Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_cod"},{"id":"minecraft:cooked_mutton","localizedName":"Cooked Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_mutton"},{"id":"minecraft:cooked_porkchop","localizedName":"Cooked Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_porkchop"},{"id":"minecraft:cooked_rabbit","localizedName":"Cooked Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_rabbit"},{"id":"minecraft:cooked_salmon","localizedName":"Cooked Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_salmon"},{"id":"minecraft:cookie","localizedName":"Cookie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cookie"},{"id":"minecraft:copper_block","localizedName":"Block of Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.copper_block"},{"id":"minecraft:copper_ingot","localizedName":"Copper Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.copper_ingot"},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.copper_ore"},{"id":"minecraft:cornflower","localizedName":"Cornflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cornflower"},{"id":"minecraft:cow_spawn_egg","localizedName":"Cow Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cow_spawn_egg"},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_bricks"},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_tiles"},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_nether_bricks"},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_polished_blackstone_bricks"},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_stone_bricks"},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crafting_table"},{"id":"minecraft:creeper_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.creeper_banner_pattern"},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.creeper_head"},{"id":"minecraft:creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.creeper_spawn_egg"},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_button"},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_door"},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence"},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence_gate"},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fungus"},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_hyphae"},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_nylium"},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_planks"},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_pressure_plate"},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_roots"},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_sign"},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_slab"},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stairs"},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stem"},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_trapdoor"},{"id":"minecraft:crossbow","localizedName":"Crossbow","maxDamage":326,"maxStackSize":1,"unlocalizedName":"item.minecraft.crossbow"},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crying_obsidian"},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper"},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_slab"},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_stairs"},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone"},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone_slab"},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone"},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone_slab"},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.cyan_banner"},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_bed"},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_candle"},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_carpet"},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete"},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete_powder"},{"id":"minecraft:cyan_dye","localizedName":"Cyan Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cyan_dye"},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_glazed_terracotta"},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_shulker_box"},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass"},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass_pane"},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_terracotta"},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_wool"},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.damaged_anvil"},{"id":"minecraft:dandelion","localizedName":"Dandelion","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dandelion"},{"id":"minecraft:dark_oak_boat","localizedName":"Dark Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_boat"},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_button"},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_door"},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence"},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence_gate"},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_leaves"},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_log"},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_planks"},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_pressure_plate"},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_sapling"},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_sign"},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_slab"},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_stairs"},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_trapdoor"},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_wood"},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine"},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_slab"},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_stairs"},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.daylight_detector"},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral"},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_block"},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_fan"},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral"},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_block"},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_fan"},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bush"},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral"},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_block"},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_fan"},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral"},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_block"},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_fan"},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral"},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_block"},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_fan"},{"id":"minecraft:debug_stick","localizedName":"Debug Stick","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.debug_stick"},{"id":"minecraft:deepslate","localizedName":"Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate"},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_slab"},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_stairs"},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_wall"},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_bricks"},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_coal_ore"},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_copper_ore"},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_diamond_ore"},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_emerald_ore"},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_gold_ore"},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_iron_ore"},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_lapis_ore"},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_redstone_ore"},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_slab"},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_stairs"},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_wall"},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tiles"},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.detector_rail"},{"id":"minecraft:diamond","localizedName":"Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.diamond"},{"id":"minecraft:diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_axe"},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_block"},{"id":"minecraft:diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_boots"},{"id":"minecraft:diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_chestplate"},{"id":"minecraft:diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_helmet"},{"id":"minecraft:diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_hoe"},{"id":"minecraft:diamond_horse_armor","localizedName":"Diamond Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_horse_armor"},{"id":"minecraft:diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_leggings"},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_ore"},{"id":"minecraft:diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_pickaxe"},{"id":"minecraft:diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_shovel"},{"id":"minecraft:diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_sword"},{"id":"minecraft:diorite","localizedName":"Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite"},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_slab"},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_stairs"},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_wall"},{"id":"minecraft:dirt","localizedName":"Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dirt"},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dirt_path"},{"id":"minecraft:dispenser","localizedName":"Dispenser","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dispenser"},{"id":"minecraft:dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dolphin_spawn_egg"},{"id":"minecraft:donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.donkey_spawn_egg"},{"id":"minecraft:dragon_breath","localizedName":"Dragon\u0027s Breath","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dragon_breath"},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_egg"},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_head"},{"id":"minecraft:dried_kelp","localizedName":"Dried Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dried_kelp"},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dried_kelp_block"},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dripstone_block"},{"id":"minecraft:dropper","localizedName":"Dropper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dropper"},{"id":"minecraft:drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.drowned_spawn_egg"},{"id":"minecraft:egg","localizedName":"Egg","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.egg"},{"id":"minecraft:elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.elder_guardian_spawn_egg"},{"id":"minecraft:elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1,"unlocalizedName":"item.minecraft.elytra"},{"id":"minecraft:emerald","localizedName":"Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.emerald"},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_block"},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_ore"},{"id":"minecraft:enchanted_book","localizedName":"Enchanted Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.enchanted_book"},{"id":"minecraft:enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enchanted_golden_apple"},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.enchanting_table"},{"id":"minecraft:end_crystal","localizedName":"End Crystal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.end_crystal"},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_portal_frame"},{"id":"minecraft:end_rod","localizedName":"End Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_rod"},{"id":"minecraft:end_stone","localizedName":"End Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone"},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_slab"},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_stairs"},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_wall"},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_bricks"},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ender_chest"},{"id":"minecraft:ender_eye","localizedName":"Eye of Ender","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ender_eye"},{"id":"minecraft:ender_pearl","localizedName":"Ender Pearl","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.ender_pearl"},{"id":"minecraft:enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enderman_spawn_egg"},{"id":"minecraft:endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.endermite_spawn_egg"},{"id":"minecraft:evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.evoker_spawn_egg"},{"id":"minecraft:experience_bottle","localizedName":"Bottle o\u0027 Enchanting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.experience_bottle"},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper"},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper"},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_slab"},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_stairs"},{"id":"minecraft:farmland","localizedName":"Farmland","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.farmland"},{"id":"minecraft:feather","localizedName":"Feather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.feather"},{"id":"minecraft:fermented_spider_eye","localizedName":"Fermented Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fermented_spider_eye"},{"id":"minecraft:fern","localizedName":"Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fern"},{"id":"minecraft:filled_map","localizedName":"Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.filled_map"},{"id":"minecraft:fire_charge","localizedName":"Fire Charge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fire_charge"},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral"},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_block"},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_fan"},{"id":"minecraft:firework_rocket","localizedName":"Firework Rocket","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_rocket"},{"id":"minecraft:firework_star","localizedName":"Firework Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_star"},{"id":"minecraft:fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.fishing_rod"},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fletching_table"},{"id":"minecraft:flint","localizedName":"Flint","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.flint"},{"id":"minecraft:flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.flint_and_steel"},{"id":"minecraft:flower_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.flower_banner_pattern"},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flower_pot"},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea"},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea_leaves"},{"id":"minecraft:fox_spawn_egg","localizedName":"Fox Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fox_spawn_egg"},{"id":"minecraft:furnace","localizedName":"Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.furnace"},{"id":"minecraft:furnace_minecart","localizedName":"Minecart with Furnace","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.furnace_minecart"},{"id":"minecraft:ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_spawn_egg"},{"id":"minecraft:ghast_tear","localizedName":"Ghast Tear","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_tear"},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gilded_blackstone"},{"id":"minecraft:glass","localizedName":"Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass"},{"id":"minecraft:glass_bottle","localizedName":"Glass Bottle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glass_bottle"},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass_pane"},{"id":"minecraft:glistering_melon_slice","localizedName":"Glistering Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glistering_melon_slice"},{"id":"minecraft:globe_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.globe_banner_pattern"},{"id":"minecraft:glow_berries","localizedName":"Glow Berries","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_berries"},{"id":"minecraft:glow_ink_sac","localizedName":"Glow Ink Sac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_ink_sac"},{"id":"minecraft:glow_item_frame","localizedName":"Glow Item Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_item_frame"},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glow_lichen"},{"id":"minecraft:glow_squid_spawn_egg","localizedName":"Glow Squid Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_squid_spawn_egg"},{"id":"minecraft:glowstone","localizedName":"Glowstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glowstone"},{"id":"minecraft:glowstone_dust","localizedName":"Glowstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glowstone_dust"},{"id":"minecraft:goat_spawn_egg","localizedName":"Goat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.goat_spawn_egg"},{"id":"minecraft:gold_block","localizedName":"Block of Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_block"},{"id":"minecraft:gold_ingot","localizedName":"Gold Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_ingot"},{"id":"minecraft:gold_nugget","localizedName":"Gold Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_nugget"},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_ore"},{"id":"minecraft:golden_apple","localizedName":"Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_apple"},{"id":"minecraft:golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_axe"},{"id":"minecraft:golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_boots"},{"id":"minecraft:golden_carrot","localizedName":"Golden Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_carrot"},{"id":"minecraft:golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_chestplate"},{"id":"minecraft:golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_helmet"},{"id":"minecraft:golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_hoe"},{"id":"minecraft:golden_horse_armor","localizedName":"Golden Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_horse_armor"},{"id":"minecraft:golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_leggings"},{"id":"minecraft:golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_pickaxe"},{"id":"minecraft:golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_shovel"},{"id":"minecraft:golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_sword"},{"id":"minecraft:granite","localizedName":"Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite"},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_slab"},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_stairs"},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_wall"},{"id":"minecraft:grass","localizedName":"Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass"},{"id":"minecraft:grass_block","localizedName":"Grass Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass_block"},{"id":"minecraft:gravel","localizedName":"Gravel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gravel"},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.gray_banner"},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_bed"},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_candle"},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_carpet"},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete"},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete_powder"},{"id":"minecraft:gray_dye","localizedName":"Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gray_dye"},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_glazed_terracotta"},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_shulker_box"},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass"},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass_pane"},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_terracotta"},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_wool"},{"id":"minecraft:green_banner","localizedName":"Green Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.green_banner"},{"id":"minecraft:green_bed","localizedName":"Green Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_bed"},{"id":"minecraft:green_candle","localizedName":"Green Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_candle"},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_carpet"},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete"},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete_powder"},{"id":"minecraft:green_dye","localizedName":"Green Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.green_dye"},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_glazed_terracotta"},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_shulker_box"},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass"},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass_pane"},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_terracotta"},{"id":"minecraft:green_wool","localizedName":"Green Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_wool"},{"id":"minecraft:grindstone","localizedName":"Grindstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grindstone"},{"id":"minecraft:guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.guardian_spawn_egg"},{"id":"minecraft:gunpowder","localizedName":"Gunpowder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gunpowder"},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hanging_roots"},{"id":"minecraft:hay_block","localizedName":"Hay Bale","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hay_block"},{"id":"minecraft:heart_of_the_sea","localizedName":"Heart of the Sea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.heart_of_the_sea"},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate"},{"id":"minecraft:hoglin_spawn_egg","localizedName":"Hoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.hoglin_spawn_egg"},{"id":"minecraft:honey_block","localizedName":"Honey Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honey_block"},{"id":"minecraft:honey_bottle","localizedName":"Honey Bottle","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.honey_bottle"},{"id":"minecraft:honeycomb","localizedName":"Honeycomb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.honeycomb"},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honeycomb_block"},{"id":"minecraft:hopper","localizedName":"Hopper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hopper"},{"id":"minecraft:hopper_minecart","localizedName":"Minecart with Hopper","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.hopper_minecart"},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral"},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_block"},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_fan"},{"id":"minecraft:horse_spawn_egg","localizedName":"Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.horse_spawn_egg"},{"id":"minecraft:husk_spawn_egg","localizedName":"Husk Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.husk_spawn_egg"},{"id":"minecraft:ice","localizedName":"Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ice"},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks"},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cobblestone"},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cracked_stone_bricks"},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_deepslate"},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_mossy_stone_bricks"},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone"},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone_bricks"},{"id":"minecraft:ink_sac","localizedName":"Ink Sac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ink_sac"},{"id":"minecraft:iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_axe"},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_bars"},{"id":"minecraft:iron_block","localizedName":"Block of Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_block"},{"id":"minecraft:iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_boots"},{"id":"minecraft:iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_chestplate"},{"id":"minecraft:iron_door","localizedName":"Iron Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_door"},{"id":"minecraft:iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_helmet"},{"id":"minecraft:iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_hoe"},{"id":"minecraft:iron_horse_armor","localizedName":"Iron Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_horse_armor"},{"id":"minecraft:iron_ingot","localizedName":"Iron Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_ingot"},{"id":"minecraft:iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_leggings"},{"id":"minecraft:iron_nugget","localizedName":"Iron Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_nugget"},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_ore"},{"id":"minecraft:iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_pickaxe"},{"id":"minecraft:iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_shovel"},{"id":"minecraft:iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_sword"},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_trapdoor"},{"id":"minecraft:item_frame","localizedName":"Item Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.item_frame"},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jack_o_lantern"},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jigsaw"},{"id":"minecraft:jukebox","localizedName":"Jukebox","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jukebox"},{"id":"minecraft:jungle_boat","localizedName":"Jungle Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_boat"},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_button"},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_door"},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence"},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence_gate"},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_leaves"},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_log"},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_planks"},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_pressure_plate"},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_sapling"},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_sign"},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_slab"},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_stairs"},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_trapdoor"},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_wood"},{"id":"minecraft:kelp","localizedName":"Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.kelp"},{"id":"minecraft:knowledge_book","localizedName":"Knowledge Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.knowledge_book"},{"id":"minecraft:ladder","localizedName":"Ladder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ladder"},{"id":"minecraft:lantern","localizedName":"Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lantern"},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_block"},{"id":"minecraft:lapis_lazuli","localizedName":"Lapis Lazuli","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lapis_lazuli"},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_ore"},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.large_amethyst_bud"},{"id":"minecraft:large_fern","localizedName":"Large Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.large_fern"},{"id":"minecraft:lava_bucket","localizedName":"Lava Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lava_bucket"},{"id":"minecraft:lead","localizedName":"Lead","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lead"},{"id":"minecraft:leather","localizedName":"Leather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.leather"},{"id":"minecraft:leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_boots"},{"id":"minecraft:leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_chestplate"},{"id":"minecraft:leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_helmet"},{"id":"minecraft:leather_horse_armor","localizedName":"Leather Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_horse_armor"},{"id":"minecraft:leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_leggings"},{"id":"minecraft:lectern","localizedName":"Lectern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lectern"},{"id":"minecraft:lever","localizedName":"Lever","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lever"},{"id":"minecraft:light","localizedName":"Light","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light"},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_blue_banner"},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_bed"},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_candle"},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_carpet"},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete"},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete_powder"},{"id":"minecraft:light_blue_dye","localizedName":"Light Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_blue_dye"},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_glazed_terracotta"},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_shulker_box"},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass"},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass_pane"},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_terracotta"},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_wool"},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_gray_banner"},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_bed"},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_candle"},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_carpet"},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete"},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete_powder"},{"id":"minecraft:light_gray_dye","localizedName":"Light Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_gray_dye"},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_glazed_terracotta"},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_shulker_box"},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass"},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass_pane"},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_terracotta"},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_wool"},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_weighted_pressure_plate"},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lightning_rod"},{"id":"minecraft:lilac","localizedName":"Lilac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lilac"},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_of_the_valley"},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_pad"},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.lime_banner"},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_bed"},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_candle"},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_carpet"},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete"},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete_powder"},{"id":"minecraft:lime_dye","localizedName":"Lime Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lime_dye"},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_glazed_terracotta"},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_shulker_box"},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass"},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass_pane"},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_terracotta"},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_wool"},{"id":"minecraft:lingering_potion","localizedName":"Lingering Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lingering_potion.effect.water"},{"id":"minecraft:llama_spawn_egg","localizedName":"Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.llama_spawn_egg"},{"id":"minecraft:lodestone","localizedName":"Lodestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lodestone"},{"id":"minecraft:loom","localizedName":"Loom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.loom"},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.magenta_banner"},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_bed"},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_candle"},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_carpet"},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete"},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete_powder"},{"id":"minecraft:magenta_dye","localizedName":"Magenta Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magenta_dye"},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_glazed_terracotta"},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_shulker_box"},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass"},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass_pane"},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_terracotta"},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_wool"},{"id":"minecraft:magma_block","localizedName":"Magma Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magma_block"},{"id":"minecraft:magma_cream","localizedName":"Magma Cream","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cream"},{"id":"minecraft:magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cube_spawn_egg"},{"id":"minecraft:map","localizedName":"Empty Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.map"},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.medium_amethyst_bud"},{"id":"minecraft:melon","localizedName":"Melon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.melon"},{"id":"minecraft:melon_seeds","localizedName":"Melon Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_seeds"},{"id":"minecraft:melon_slice","localizedName":"Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_slice"},{"id":"minecraft:milk_bucket","localizedName":"Milk Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.milk_bucket"},{"id":"minecraft:minecart","localizedName":"Minecart","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.minecart"},{"id":"minecraft:mojang_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mojang_banner_pattern"},{"id":"minecraft:mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mooshroom_spawn_egg"},{"id":"minecraft:moss_block","localizedName":"Moss Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.moss_block"},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.moss_carpet"},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone"},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_slab"},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_stairs"},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_wall"},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_slab"},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_stairs"},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_wall"},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_bricks"},{"id":"minecraft:mule_spawn_egg","localizedName":"Mule Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mule_spawn_egg"},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mushroom_stem"},{"id":"minecraft:mushroom_stew","localizedName":"Mushroom Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mushroom_stew"},{"id":"minecraft:music_disc_11","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_11"},{"id":"minecraft:music_disc_13","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_13"},{"id":"minecraft:music_disc_blocks","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_blocks"},{"id":"minecraft:music_disc_cat","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_cat"},{"id":"minecraft:music_disc_chirp","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_chirp"},{"id":"minecraft:music_disc_far","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_far"},{"id":"minecraft:music_disc_mall","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mall"},{"id":"minecraft:music_disc_mellohi","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mellohi"},{"id":"minecraft:music_disc_pigstep","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_pigstep"},{"id":"minecraft:music_disc_stal","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_stal"},{"id":"minecraft:music_disc_strad","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_strad"},{"id":"minecraft:music_disc_wait","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_wait"},{"id":"minecraft:music_disc_ward","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_ward"},{"id":"minecraft:mutton","localizedName":"Raw Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mutton"},{"id":"minecraft:mycelium","localizedName":"Mycelium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mycelium"},{"id":"minecraft:name_tag","localizedName":"Name Tag","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.name_tag"},{"id":"minecraft:nautilus_shell","localizedName":"Nautilus Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nautilus_shell"},{"id":"minecraft:nether_brick","localizedName":"Nether Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_brick"},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_fence"},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_slab"},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_stairs"},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_wall"},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_bricks"},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_gold_ore"},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_quartz_ore"},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_sprouts"},{"id":"minecraft:nether_star","localizedName":"Nether Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_star"},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_wart"},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_wart_block"},{"id":"minecraft:netherite_axe","localizedName":"Netherite Axe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_axe"},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherite_block"},{"id":"minecraft:netherite_boots","localizedName":"Netherite Boots","maxDamage":481,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_boots"},{"id":"minecraft:netherite_chestplate","localizedName":"Netherite Chestplate","maxDamage":592,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_chestplate"},{"id":"minecraft:netherite_helmet","localizedName":"Netherite Helmet","maxDamage":407,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_helmet"},{"id":"minecraft:netherite_hoe","localizedName":"Netherite Hoe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_hoe"},{"id":"minecraft:netherite_ingot","localizedName":"Netherite Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_ingot"},{"id":"minecraft:netherite_leggings","localizedName":"Netherite Leggings","maxDamage":555,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_leggings"},{"id":"minecraft:netherite_pickaxe","localizedName":"Netherite Pickaxe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_pickaxe"},{"id":"minecraft:netherite_scrap","localizedName":"Netherite Scrap","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_scrap"},{"id":"minecraft:netherite_shovel","localizedName":"Netherite Shovel","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_shovel"},{"id":"minecraft:netherite_sword","localizedName":"Netherite Sword","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_sword"},{"id":"minecraft:netherrack","localizedName":"Netherrack","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherrack"},{"id":"minecraft:note_block","localizedName":"Note Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.note_block"},{"id":"minecraft:oak_boat","localizedName":"Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.oak_boat"},{"id":"minecraft:oak_button","localizedName":"Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_button"},{"id":"minecraft:oak_door","localizedName":"Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_door"},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence"},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence_gate"},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_leaves"},{"id":"minecraft:oak_log","localizedName":"Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_log"},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_planks"},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_pressure_plate"},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_sapling"},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.oak_sign"},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_slab"},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_stairs"},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_trapdoor"},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_wood"},{"id":"minecraft:observer","localizedName":"Observer","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.observer"},{"id":"minecraft:obsidian","localizedName":"Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.obsidian"},{"id":"minecraft:ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ocelot_spawn_egg"},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.orange_banner"},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_bed"},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_candle"},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_carpet"},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete"},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete_powder"},{"id":"minecraft:orange_dye","localizedName":"Orange Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.orange_dye"},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_glazed_terracotta"},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_shulker_box"},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass"},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass_pane"},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_terracotta"},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_tulip"},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_wool"},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxeye_daisy"},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper"},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper"},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_slab"},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_stairs"},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.packed_ice"},{"id":"minecraft:painting","localizedName":"Painting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.painting"},{"id":"minecraft:panda_spawn_egg","localizedName":"Panda Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.panda_spawn_egg"},{"id":"minecraft:paper","localizedName":"Paper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.paper"},{"id":"minecraft:parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.parrot_spawn_egg"},{"id":"minecraft:peony","localizedName":"Peony","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.peony"},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.petrified_oak_slab"},{"id":"minecraft:phantom_membrane","localizedName":"Phantom Membrane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_membrane"},{"id":"minecraft:phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_spawn_egg"},{"id":"minecraft:pig_spawn_egg","localizedName":"Pig Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pig_spawn_egg"},{"id":"minecraft:piglin_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.piglin_banner_pattern"},{"id":"minecraft:piglin_brute_spawn_egg","localizedName":"Piglin Brute Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_brute_spawn_egg"},{"id":"minecraft:piglin_spawn_egg","localizedName":"Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_spawn_egg"},{"id":"minecraft:pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pillager_spawn_egg"},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.pink_banner"},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_bed"},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_candle"},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_carpet"},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete"},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete_powder"},{"id":"minecraft:pink_dye","localizedName":"Pink Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pink_dye"},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_glazed_terracotta"},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_shulker_box"},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass"},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass_pane"},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_terracotta"},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_tulip"},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_wool"},{"id":"minecraft:piston","localizedName":"Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.piston"},{"id":"minecraft:player_head","localizedName":"Player Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.player_head"},{"id":"minecraft:podzol","localizedName":"Podzol","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.podzol"},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pointed_dripstone"},{"id":"minecraft:poisonous_potato","localizedName":"Poisonous Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.poisonous_potato"},{"id":"minecraft:polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.polar_bear_spawn_egg"},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite"},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_slab"},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_stairs"},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_basalt"},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone"},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_slab"},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_stairs"},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_wall"},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_bricks"},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_button"},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_pressure_plate"},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_slab"},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_stairs"},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_wall"},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate"},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_slab"},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_stairs"},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_wall"},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite"},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_slab"},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_stairs"},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite"},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_slab"},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_stairs"},{"id":"minecraft:popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.popped_chorus_fruit"},{"id":"minecraft:poppy","localizedName":"Poppy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.poppy"},{"id":"minecraft:porkchop","localizedName":"Raw Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.porkchop"},{"id":"minecraft:potato","localizedName":"Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.potato"},{"id":"minecraft:potion","localizedName":"Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.potion.effect.water"},{"id":"minecraft:powder_snow_bucket","localizedName":"Powder Snow Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.powder_snow_bucket"},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.powered_rail"},{"id":"minecraft:prismarine","localizedName":"Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine"},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_slab"},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_stairs"},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_bricks"},{"id":"minecraft:prismarine_crystals","localizedName":"Prismarine Crystals","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_crystals"},{"id":"minecraft:prismarine_shard","localizedName":"Prismarine Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_shard"},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_slab"},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_stairs"},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_wall"},{"id":"minecraft:pufferfish","localizedName":"Pufferfish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish"},{"id":"minecraft:pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.pufferfish_bucket"},{"id":"minecraft:pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish_spawn_egg"},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pumpkin"},{"id":"minecraft:pumpkin_pie","localizedName":"Pumpkin Pie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_pie"},{"id":"minecraft:pumpkin_seeds","localizedName":"Pumpkin Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_seeds"},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.purple_banner"},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_bed"},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_candle"},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_carpet"},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete"},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete_powder"},{"id":"minecraft:purple_dye","localizedName":"Purple Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.purple_dye"},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_glazed_terracotta"},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_shulker_box"},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass"},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass_pane"},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_terracotta"},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_wool"},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_block"},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_pillar"},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_slab"},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_stairs"},{"id":"minecraft:quartz","localizedName":"Nether Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.quartz"},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_block"},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_bricks"},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_pillar"},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_slab"},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_stairs"},{"id":"minecraft:rabbit","localizedName":"Raw Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit"},{"id":"minecraft:rabbit_foot","localizedName":"Rabbit\u0027s Foot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_foot"},{"id":"minecraft:rabbit_hide","localizedName":"Rabbit Hide","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_hide"},{"id":"minecraft:rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_spawn_egg"},{"id":"minecraft:rabbit_stew","localizedName":"Rabbit Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.rabbit_stew"},{"id":"minecraft:rail","localizedName":"Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rail"},{"id":"minecraft:ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ravager_spawn_egg"},{"id":"minecraft:raw_copper","localizedName":"Raw Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_copper"},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_copper_block"},{"id":"minecraft:raw_gold","localizedName":"Raw Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_gold"},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_gold_block"},{"id":"minecraft:raw_iron","localizedName":"Raw Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_iron"},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_iron_block"},{"id":"minecraft:red_banner","localizedName":"Red Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.red_banner"},{"id":"minecraft:red_bed","localizedName":"Red Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_bed"},{"id":"minecraft:red_candle","localizedName":"Red Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_candle"},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_carpet"},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete"},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete_powder"},{"id":"minecraft:red_dye","localizedName":"Red Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.red_dye"},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_glazed_terracotta"},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom"},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom_block"},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_slab"},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_stairs"},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_wall"},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_bricks"},{"id":"minecraft:red_sand","localizedName":"Red Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sand"},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone"},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_slab"},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_stairs"},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_wall"},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_shulker_box"},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass"},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass_pane"},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_terracotta"},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_tulip"},{"id":"minecraft:red_wool","localizedName":"Red Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_wool"},{"id":"minecraft:redstone","localizedName":"Redstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.redstone"},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_block"},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_lamp"},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_ore"},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_torch"},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeater"},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeating_command_block"},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.respawn_anchor"},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rooted_dirt"},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rose_bush"},{"id":"minecraft:rotten_flesh","localizedName":"Rotten Flesh","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rotten_flesh"},{"id":"minecraft:saddle","localizedName":"Saddle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.saddle"},{"id":"minecraft:salmon","localizedName":"Raw Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon"},{"id":"minecraft:salmon_bucket","localizedName":"Bucket of Salmon","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.salmon_bucket"},{"id":"minecraft:salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon_spawn_egg"},{"id":"minecraft:sand","localizedName":"Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sand"},{"id":"minecraft:sandstone","localizedName":"Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone"},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_slab"},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_stairs"},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_wall"},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.scaffolding"},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_sensor"},{"id":"minecraft:scute","localizedName":"Scute","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.scute"},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_lantern"},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_pickle"},{"id":"minecraft:seagrass","localizedName":"Seagrass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.seagrass"},{"id":"minecraft:shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1,"unlocalizedName":"item.minecraft.shears"},{"id":"minecraft:sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sheep_spawn_egg"},{"id":"minecraft:shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1,"unlocalizedName":"item.minecraft.shield"},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.shroomlight"},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.shulker_box"},{"id":"minecraft:shulker_shell","localizedName":"Shulker Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_shell"},{"id":"minecraft:shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_spawn_egg"},{"id":"minecraft:silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.silverfish_spawn_egg"},{"id":"minecraft:skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg"},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.skeleton_skull"},{"id":"minecraft:skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_spawn_egg"},{"id":"minecraft:skull_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.skull_banner_pattern"},{"id":"minecraft:slime_ball","localizedName":"Slimeball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_ball"},{"id":"minecraft:slime_block","localizedName":"Slime Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.slime_block"},{"id":"minecraft:slime_spawn_egg","localizedName":"Slime Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_spawn_egg"},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.small_amethyst_bud"},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.small_dripleaf"},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smithing_table"},{"id":"minecraft:smoker","localizedName":"Smoker","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smoker"},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_basalt"},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz"},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_slab"},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_stairs"},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone"},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_slab"},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs"},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone"},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_slab"},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_stairs"},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone"},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone_slab"},{"id":"minecraft:snow","localizedName":"Snow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow"},{"id":"minecraft:snow_block","localizedName":"Snow Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow_block"},{"id":"minecraft:snowball","localizedName":"Snowball","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.snowball"},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_campfire"},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_lantern"},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_sand"},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_soil"},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_torch"},{"id":"minecraft:spawner","localizedName":"Spawner","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spawner"},{"id":"minecraft:spectral_arrow","localizedName":"Spectral Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spectral_arrow"},{"id":"minecraft:spider_eye","localizedName":"Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_eye"},{"id":"minecraft:spider_spawn_egg","localizedName":"Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_spawn_egg"},{"id":"minecraft:splash_potion","localizedName":"Splash Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.splash_potion.effect.water"},{"id":"minecraft:sponge","localizedName":"Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sponge"},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spore_blossom"},{"id":"minecraft:spruce_boat","localizedName":"Spruce Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_boat"},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_button"},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_door"},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence"},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence_gate"},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_leaves"},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_log"},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_planks"},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_pressure_plate"},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_sapling"},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_sign"},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_slab"},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_stairs"},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_trapdoor"},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_wood"},{"id":"minecraft:spyglass","localizedName":"Spyglass","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spyglass"},{"id":"minecraft:squid_spawn_egg","localizedName":"Squid Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.squid_spawn_egg"},{"id":"minecraft:stick","localizedName":"Stick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stick"},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sticky_piston"},{"id":"minecraft:stone","localizedName":"Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone"},{"id":"minecraft:stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_axe"},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_slab"},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_stairs"},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_wall"},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_bricks"},{"id":"minecraft:stone_button","localizedName":"Stone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_button"},{"id":"minecraft:stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_hoe"},{"id":"minecraft:stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_pickaxe"},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_pressure_plate"},{"id":"minecraft:stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_shovel"},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_slab"},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_stairs"},{"id":"minecraft:stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_sword"},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stonecutter"},{"id":"minecraft:stray_spawn_egg","localizedName":"Stray Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stray_spawn_egg"},{"id":"minecraft:strider_spawn_egg","localizedName":"Strider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.strider_spawn_egg"},{"id":"minecraft:string","localizedName":"String","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.string"},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_log"},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_wood"},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_log"},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_wood"},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_hyphae"},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_stem"},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_log"},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_wood"},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_log"},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_wood"},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_log"},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_wood"},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_log"},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_wood"},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_hyphae"},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_stem"},{"id":"minecraft:structure_block","localizedName":"Structure Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_block"},{"id":"minecraft:structure_void","localizedName":"Structure Void","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_void"},{"id":"minecraft:sugar","localizedName":"Sugar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sugar"},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sugar_cane"},{"id":"minecraft:sunflower","localizedName":"Sunflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sunflower"},{"id":"minecraft:suspicious_stew","localizedName":"Suspicious Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.suspicious_stew"},{"id":"minecraft:sweet_berries","localizedName":"Sweet Berries","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sweet_berries"},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tall_grass"},{"id":"minecraft:target","localizedName":"Target","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.target"},{"id":"minecraft:terracotta","localizedName":"Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.terracotta"},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tinted_glass"},{"id":"minecraft:tipped_arrow","localizedName":"Arrow of Poison","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tipped_arrow.effect.poison"},{"id":"minecraft:tnt","localizedName":"TNT","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tnt"},{"id":"minecraft:tnt_minecart","localizedName":"Minecart with TNT","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tnt_minecart"},{"id":"minecraft:torch","localizedName":"Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.torch"},{"id":"minecraft:totem_of_undying","localizedName":"Totem of Undying","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.totem_of_undying"},{"id":"minecraft:trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.trader_llama_spawn_egg"},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.trapped_chest"},{"id":"minecraft:trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.trident"},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tripwire_hook"},{"id":"minecraft:tropical_fish","localizedName":"Tropical Fish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish"},{"id":"minecraft:tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tropical_fish_bucket"},{"id":"minecraft:tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish_spawn_egg"},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral"},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_block"},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_fan"},{"id":"minecraft:tuff","localizedName":"Tuff","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tuff"},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.turtle_egg"},{"id":"minecraft:turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1,"unlocalizedName":"item.minecraft.turtle_helmet"},{"id":"minecraft:turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_spawn_egg"},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.twisting_vines"},{"id":"minecraft:vex_spawn_egg","localizedName":"Vex Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vex_spawn_egg"},{"id":"minecraft:villager_spawn_egg","localizedName":"Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.villager_spawn_egg"},{"id":"minecraft:vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vindicator_spawn_egg"},{"id":"minecraft:vine","localizedName":"Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.vine"},{"id":"minecraft:wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wandering_trader_spawn_egg"},{"id":"minecraft:warped_button","localizedName":"Warped Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_button"},{"id":"minecraft:warped_door","localizedName":"Warped Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_door"},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence"},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence_gate"},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fungus"},{"id":"minecraft:warped_fungus_on_a_stick","localizedName":"Warped Fungus on a Stick","maxDamage":100,"maxStackSize":1,"unlocalizedName":"item.minecraft.warped_fungus_on_a_stick"},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_hyphae"},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_nylium"},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_planks"},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_pressure_plate"},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_roots"},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.warped_sign"},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_slab"},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stairs"},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stem"},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_trapdoor"},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_wart_block"},{"id":"minecraft:water_bucket","localizedName":"Water Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.water_bucket"},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_block"},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper"},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_slab"},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_stairs"},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper"},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper"},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_slab"},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_stairs"},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper"},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper"},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_slab"},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_stairs"},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper"},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper"},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_slab"},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_stairs"},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper"},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper"},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_slab"},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_stairs"},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weeping_vines"},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wet_sponge"},{"id":"minecraft:wheat","localizedName":"Wheat","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat"},{"id":"minecraft:wheat_seeds","localizedName":"Wheat Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat_seeds"},{"id":"minecraft:white_banner","localizedName":"White Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.white_banner"},{"id":"minecraft:white_bed","localizedName":"White Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_bed"},{"id":"minecraft:white_candle","localizedName":"White Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_candle"},{"id":"minecraft:white_carpet","localizedName":"White Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_carpet"},{"id":"minecraft:white_concrete","localizedName":"White Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete"},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete_powder"},{"id":"minecraft:white_dye","localizedName":"White Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.white_dye"},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_glazed_terracotta"},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_shulker_box"},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass"},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass_pane"},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_terracotta"},{"id":"minecraft:white_tulip","localizedName":"White Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_tulip"},{"id":"minecraft:white_wool","localizedName":"White Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_wool"},{"id":"minecraft:witch_spawn_egg","localizedName":"Witch Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.witch_spawn_egg"},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_rose"},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_skeleton_skull"},{"id":"minecraft:wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg"},{"id":"minecraft:wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wolf_spawn_egg"},{"id":"minecraft:wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_axe"},{"id":"minecraft:wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_hoe"},{"id":"minecraft:wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_pickaxe"},{"id":"minecraft:wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_shovel"},{"id":"minecraft:wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_sword"},{"id":"minecraft:writable_book","localizedName":"Book and Quill","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.writable_book"},{"id":"minecraft:written_book","localizedName":"Written Book","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.written_book"},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.yellow_banner"},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_bed"},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_candle"},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_carpet"},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete"},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete_powder"},{"id":"minecraft:yellow_dye","localizedName":"Yellow Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.yellow_dye"},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_glazed_terracotta"},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_shulker_box"},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass"},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass_pane"},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_terracotta"},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_wool"},{"id":"minecraft:zoglin_spawn_egg","localizedName":"Zoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zoglin_spawn_egg"},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.zombie_head"},{"id":"minecraft:zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_horse_spawn_egg"},{"id":"minecraft:zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_spawn_egg"},{"id":"minecraft:zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_villager_spawn_egg"},{"id":"minecraft:zombified_piglin_spawn_egg","localizedName":"Zombified Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombified_piglin_spawn_egg"}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.119.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.119.json deleted file mode 100644 index 4166656e3..000000000 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.119.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"minecraft:acacia_boat","localizedName":"Acacia Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_boat"},{"id":"minecraft:acacia_button","localizedName":"Acacia Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_button"},{"id":"minecraft:acacia_chest_boat","localizedName":"Acacia Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_chest_boat"},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_door"},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence"},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence_gate"},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_leaves"},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_log"},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_planks"},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_pressure_plate"},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_sapling"},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_sign"},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_slab"},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_stairs"},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_trapdoor"},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_wood"},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.activator_rail"},{"id":"minecraft:air","localizedName":"Air","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.air"},{"id":"minecraft:allay_spawn_egg","localizedName":"Allay Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.allay_spawn_egg"},{"id":"minecraft:allium","localizedName":"Allium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.allium"},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_block"},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_cluster"},{"id":"minecraft:amethyst_shard","localizedName":"Amethyst Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.amethyst_shard"},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ancient_debris"},{"id":"minecraft:andesite","localizedName":"Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite"},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_slab"},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_stairs"},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_wall"},{"id":"minecraft:anvil","localizedName":"Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.anvil"},{"id":"minecraft:apple","localizedName":"Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.apple"},{"id":"minecraft:armor_stand","localizedName":"Armor Stand","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.armor_stand"},{"id":"minecraft:arrow","localizedName":"Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.arrow"},{"id":"minecraft:axolotl_bucket","localizedName":"Bucket of Axolotl","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.axolotl_bucket"},{"id":"minecraft:axolotl_spawn_egg","localizedName":"Axolotl Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.axolotl_spawn_egg"},{"id":"minecraft:azalea","localizedName":"Azalea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azalea"},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azalea_leaves"},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.azure_bluet"},{"id":"minecraft:baked_potato","localizedName":"Baked Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.baked_potato"},{"id":"minecraft:bamboo","localizedName":"Bamboo","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo"},{"id":"minecraft:barrel","localizedName":"Barrel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrel"},{"id":"minecraft:barrier","localizedName":"Barrier","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.barrier"},{"id":"minecraft:basalt","localizedName":"Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.basalt"},{"id":"minecraft:bat_spawn_egg","localizedName":"Bat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bat_spawn_egg"},{"id":"minecraft:beacon","localizedName":"Beacon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beacon"},{"id":"minecraft:bedrock","localizedName":"Bedrock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bedrock"},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bee_nest"},{"id":"minecraft:bee_spawn_egg","localizedName":"Bee Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bee_spawn_egg"},{"id":"minecraft:beef","localizedName":"Raw Beef","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beef"},{"id":"minecraft:beehive","localizedName":"Beehive","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.beehive"},{"id":"minecraft:beetroot","localizedName":"Beetroot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot"},{"id":"minecraft:beetroot_seeds","localizedName":"Beetroot Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot_seeds"},{"id":"minecraft:beetroot_soup","localizedName":"Beetroot Soup","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.beetroot_soup"},{"id":"minecraft:bell","localizedName":"Bell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bell"},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.big_dripleaf"},{"id":"minecraft:birch_boat","localizedName":"Birch Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.birch_boat"},{"id":"minecraft:birch_button","localizedName":"Birch Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_button"},{"id":"minecraft:birch_chest_boat","localizedName":"Birch Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.birch_chest_boat"},{"id":"minecraft:birch_door","localizedName":"Birch Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_door"},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence"},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence_gate"},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_leaves"},{"id":"minecraft:birch_log","localizedName":"Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_log"},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_planks"},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_pressure_plate"},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_sapling"},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.birch_sign"},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_slab"},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_stairs"},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_trapdoor"},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.birch_wood"},{"id":"minecraft:black_banner","localizedName":"Black Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.black_banner"},{"id":"minecraft:black_bed","localizedName":"Black Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_bed"},{"id":"minecraft:black_candle","localizedName":"Black Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_candle"},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_carpet"},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete"},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete_powder"},{"id":"minecraft:black_dye","localizedName":"Black Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.black_dye"},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_glazed_terracotta"},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.black_shulker_box"},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass"},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass_pane"},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_terracotta"},{"id":"minecraft:black_wool","localizedName":"Black Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.black_wool"},{"id":"minecraft:blackstone","localizedName":"Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone"},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_slab"},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_stairs"},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_wall"},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blast_furnace"},{"id":"minecraft:blaze_powder","localizedName":"Blaze Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_powder"},{"id":"minecraft:blaze_rod","localizedName":"Blaze Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_rod"},{"id":"minecraft:blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_spawn_egg"},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.blue_banner"},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_bed"},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_candle"},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_carpet"},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete"},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete_powder"},{"id":"minecraft:blue_dye","localizedName":"Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.blue_dye"},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_glazed_terracotta"},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_ice"},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_orchid"},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.blue_shulker_box"},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass"},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass_pane"},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_terracotta"},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.blue_wool"},{"id":"minecraft:bone","localizedName":"Bone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone"},{"id":"minecraft:bone_block","localizedName":"Bone Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bone_block"},{"id":"minecraft:bone_meal","localizedName":"Bone Meal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bone_meal"},{"id":"minecraft:book","localizedName":"Book","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.book"},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bookshelf"},{"id":"minecraft:bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1,"unlocalizedName":"item.minecraft.bow"},{"id":"minecraft:bowl","localizedName":"Bowl","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bowl"},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral"},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_block"},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_fan"},{"id":"minecraft:bread","localizedName":"Bread","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.bread"},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brewing_stand"},{"id":"minecraft:brick","localizedName":"Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brick"},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_slab"},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_stairs"},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brick_wall"},{"id":"minecraft:bricks","localizedName":"Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bricks"},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.brown_banner"},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_bed"},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_candle"},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_carpet"},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete"},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete_powder"},{"id":"minecraft:brown_dye","localizedName":"Brown Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.brown_dye"},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_glazed_terracotta"},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom"},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom_block"},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.brown_shulker_box"},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass"},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass_pane"},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_terracotta"},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.brown_wool"},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral"},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_block"},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_fan"},{"id":"minecraft:bucket","localizedName":"Bucket","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.bucket"},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.budding_amethyst"},{"id":"minecraft:bundle","localizedName":"Bundle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.bundle"},{"id":"minecraft:cactus","localizedName":"Cactus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cactus"},{"id":"minecraft:cake","localizedName":"Cake","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cake"},{"id":"minecraft:calcite","localizedName":"Calcite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.calcite"},{"id":"minecraft:campfire","localizedName":"Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.campfire"},{"id":"minecraft:candle","localizedName":"Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.candle"},{"id":"minecraft:carrot","localizedName":"Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.carrot"},{"id":"minecraft:carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1,"unlocalizedName":"item.minecraft.carrot_on_a_stick"},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cartography_table"},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.carved_pumpkin"},{"id":"minecraft:cat_spawn_egg","localizedName":"Cat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cat_spawn_egg"},{"id":"minecraft:cauldron","localizedName":"Cauldron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cauldron"},{"id":"minecraft:cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cave_spider_spawn_egg"},{"id":"minecraft:chain","localizedName":"Chain","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain"},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chain_command_block"},{"id":"minecraft:chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_boots"},{"id":"minecraft:chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_chestplate"},{"id":"minecraft:chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_helmet"},{"id":"minecraft:chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_leggings"},{"id":"minecraft:charcoal","localizedName":"Charcoal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.charcoal"},{"id":"minecraft:chest","localizedName":"Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chest"},{"id":"minecraft:chest_minecart","localizedName":"Minecart with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.chest_minecart"},{"id":"minecraft:chicken","localizedName":"Raw Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken"},{"id":"minecraft:chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chicken_spawn_egg"},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chipped_anvil"},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_deepslate"},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_nether_bricks"},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_polished_blackstone"},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_quartz_block"},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_red_sandstone"},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_sandstone"},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_stone_bricks"},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_flower"},{"id":"minecraft:chorus_fruit","localizedName":"Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.chorus_fruit"},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_plant"},{"id":"minecraft:clay","localizedName":"Clay","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.clay"},{"id":"minecraft:clay_ball","localizedName":"Clay Ball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clay_ball"},{"id":"minecraft:clock","localizedName":"Clock","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.clock"},{"id":"minecraft:coal","localizedName":"Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.coal"},{"id":"minecraft:coal_block","localizedName":"Block of Coal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_block"},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coal_ore"},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.coarse_dirt"},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate"},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_slab"},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_stairs"},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_wall"},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone"},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_slab"},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_stairs"},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_wall"},{"id":"minecraft:cobweb","localizedName":"Cobweb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cobweb"},{"id":"minecraft:cocoa_beans","localizedName":"Cocoa Beans","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cocoa_beans"},{"id":"minecraft:cod","localizedName":"Raw Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod"},{"id":"minecraft:cod_bucket","localizedName":"Bucket of Cod","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.cod_bucket"},{"id":"minecraft:cod_spawn_egg","localizedName":"Cod Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cod_spawn_egg"},{"id":"minecraft:command_block","localizedName":"Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.command_block"},{"id":"minecraft:command_block_minecart","localizedName":"Minecart with Command Block","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.command_block_minecart"},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.comparator"},{"id":"minecraft:compass","localizedName":"Compass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.compass"},{"id":"minecraft:composter","localizedName":"Composter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.composter"},{"id":"minecraft:conduit","localizedName":"Conduit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.conduit"},{"id":"minecraft:cooked_beef","localizedName":"Steak","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_beef"},{"id":"minecraft:cooked_chicken","localizedName":"Cooked Chicken","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_chicken"},{"id":"minecraft:cooked_cod","localizedName":"Cooked Cod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_cod"},{"id":"minecraft:cooked_mutton","localizedName":"Cooked Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_mutton"},{"id":"minecraft:cooked_porkchop","localizedName":"Cooked Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_porkchop"},{"id":"minecraft:cooked_rabbit","localizedName":"Cooked Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_rabbit"},{"id":"minecraft:cooked_salmon","localizedName":"Cooked Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_salmon"},{"id":"minecraft:cookie","localizedName":"Cookie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cookie"},{"id":"minecraft:copper_block","localizedName":"Block of Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.copper_block"},{"id":"minecraft:copper_ingot","localizedName":"Copper Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.copper_ingot"},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.copper_ore"},{"id":"minecraft:cornflower","localizedName":"Cornflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cornflower"},{"id":"minecraft:cow_spawn_egg","localizedName":"Cow Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cow_spawn_egg"},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_bricks"},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_tiles"},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_nether_bricks"},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_polished_blackstone_bricks"},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_stone_bricks"},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crafting_table"},{"id":"minecraft:creeper_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.creeper_banner_pattern"},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.creeper_head"},{"id":"minecraft:creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.creeper_spawn_egg"},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_button"},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_door"},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence"},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence_gate"},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fungus"},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_hyphae"},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_nylium"},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_planks"},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_pressure_plate"},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_roots"},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_sign"},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_slab"},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stairs"},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stem"},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_trapdoor"},{"id":"minecraft:crossbow","localizedName":"Crossbow","maxDamage":465,"maxStackSize":1,"unlocalizedName":"item.minecraft.crossbow"},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.crying_obsidian"},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper"},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_slab"},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_stairs"},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone"},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone_slab"},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone"},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone_slab"},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.cyan_banner"},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_bed"},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_candle"},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_carpet"},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete"},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete_powder"},{"id":"minecraft:cyan_dye","localizedName":"Cyan Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.cyan_dye"},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_glazed_terracotta"},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_shulker_box"},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass"},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass_pane"},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_terracotta"},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_wool"},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.damaged_anvil"},{"id":"minecraft:dandelion","localizedName":"Dandelion","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dandelion"},{"id":"minecraft:dark_oak_boat","localizedName":"Dark Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_boat"},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_button"},{"id":"minecraft:dark_oak_chest_boat","localizedName":"Dark Oak Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_chest_boat"},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_door"},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence"},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence_gate"},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_leaves"},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_log"},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_planks"},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_pressure_plate"},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_sapling"},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_sign"},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_slab"},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_stairs"},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_trapdoor"},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_wood"},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine"},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_slab"},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_stairs"},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.daylight_detector"},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral"},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_block"},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_fan"},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral"},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_block"},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_fan"},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bush"},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral"},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_block"},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_fan"},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral"},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_block"},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_fan"},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral"},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_block"},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_fan"},{"id":"minecraft:debug_stick","localizedName":"Debug Stick","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.debug_stick"},{"id":"minecraft:deepslate","localizedName":"Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate"},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_slab"},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_stairs"},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_wall"},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_bricks"},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_coal_ore"},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_copper_ore"},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_diamond_ore"},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_emerald_ore"},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_gold_ore"},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_iron_ore"},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_lapis_ore"},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_redstone_ore"},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_slab"},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_stairs"},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_wall"},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tiles"},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.detector_rail"},{"id":"minecraft:diamond","localizedName":"Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.diamond"},{"id":"minecraft:diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_axe"},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_block"},{"id":"minecraft:diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_boots"},{"id":"minecraft:diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_chestplate"},{"id":"minecraft:diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_helmet"},{"id":"minecraft:diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_hoe"},{"id":"minecraft:diamond_horse_armor","localizedName":"Diamond Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_horse_armor"},{"id":"minecraft:diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_leggings"},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_ore"},{"id":"minecraft:diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_pickaxe"},{"id":"minecraft:diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_shovel"},{"id":"minecraft:diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_sword"},{"id":"minecraft:diorite","localizedName":"Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite"},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_slab"},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_stairs"},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_wall"},{"id":"minecraft:dirt","localizedName":"Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dirt"},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dirt_path"},{"id":"minecraft:disc_fragment_5","localizedName":"Disc Fragment","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.disc_fragment_5"},{"id":"minecraft:dispenser","localizedName":"Dispenser","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dispenser"},{"id":"minecraft:dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dolphin_spawn_egg"},{"id":"minecraft:donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.donkey_spawn_egg"},{"id":"minecraft:dragon_breath","localizedName":"Dragon\u0027s Breath","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dragon_breath"},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_egg"},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_head"},{"id":"minecraft:dried_kelp","localizedName":"Dried Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.dried_kelp"},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dried_kelp_block"},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dripstone_block"},{"id":"minecraft:dropper","localizedName":"Dropper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.dropper"},{"id":"minecraft:drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.drowned_spawn_egg"},{"id":"minecraft:echo_shard","localizedName":"Echo Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.echo_shard"},{"id":"minecraft:egg","localizedName":"Egg","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.egg"},{"id":"minecraft:elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.elder_guardian_spawn_egg"},{"id":"minecraft:elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1,"unlocalizedName":"item.minecraft.elytra"},{"id":"minecraft:emerald","localizedName":"Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.emerald"},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_block"},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_ore"},{"id":"minecraft:enchanted_book","localizedName":"Enchanted Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.enchanted_book"},{"id":"minecraft:enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enchanted_golden_apple"},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.enchanting_table"},{"id":"minecraft:end_crystal","localizedName":"End Crystal","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.end_crystal"},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_portal_frame"},{"id":"minecraft:end_rod","localizedName":"End Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_rod"},{"id":"minecraft:end_stone","localizedName":"End Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone"},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_slab"},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_stairs"},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_wall"},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_bricks"},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ender_chest"},{"id":"minecraft:ender_eye","localizedName":"Eye of Ender","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ender_eye"},{"id":"minecraft:ender_pearl","localizedName":"Ender Pearl","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.ender_pearl"},{"id":"minecraft:enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.enderman_spawn_egg"},{"id":"minecraft:endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.endermite_spawn_egg"},{"id":"minecraft:evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.evoker_spawn_egg"},{"id":"minecraft:experience_bottle","localizedName":"Bottle o\u0027 Enchanting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.experience_bottle"},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper"},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper"},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_slab"},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_stairs"},{"id":"minecraft:farmland","localizedName":"Farmland","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.farmland"},{"id":"minecraft:feather","localizedName":"Feather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.feather"},{"id":"minecraft:fermented_spider_eye","localizedName":"Fermented Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fermented_spider_eye"},{"id":"minecraft:fern","localizedName":"Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fern"},{"id":"minecraft:filled_map","localizedName":"Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.filled_map"},{"id":"minecraft:fire_charge","localizedName":"Fire Charge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fire_charge"},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral"},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_block"},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_fan"},{"id":"minecraft:firework_rocket","localizedName":"Firework Rocket","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_rocket"},{"id":"minecraft:firework_star","localizedName":"Firework Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.firework_star"},{"id":"minecraft:fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.fishing_rod"},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.fletching_table"},{"id":"minecraft:flint","localizedName":"Flint","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.flint"},{"id":"minecraft:flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.flint_and_steel"},{"id":"minecraft:flower_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.flower_banner_pattern"},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flower_pot"},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea"},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea_leaves"},{"id":"minecraft:fox_spawn_egg","localizedName":"Fox Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.fox_spawn_egg"},{"id":"minecraft:frog_spawn_egg","localizedName":"Frog Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.frog_spawn_egg"},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.frogspawn"},{"id":"minecraft:furnace","localizedName":"Furnace","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.furnace"},{"id":"minecraft:furnace_minecart","localizedName":"Minecart with Furnace","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.furnace_minecart"},{"id":"minecraft:ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_spawn_egg"},{"id":"minecraft:ghast_tear","localizedName":"Ghast Tear","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_tear"},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gilded_blackstone"},{"id":"minecraft:glass","localizedName":"Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass"},{"id":"minecraft:glass_bottle","localizedName":"Glass Bottle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glass_bottle"},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glass_pane"},{"id":"minecraft:glistering_melon_slice","localizedName":"Glistering Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glistering_melon_slice"},{"id":"minecraft:globe_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.globe_banner_pattern"},{"id":"minecraft:glow_berries","localizedName":"Glow Berries","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_berries"},{"id":"minecraft:glow_ink_sac","localizedName":"Glow Ink Sac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_ink_sac"},{"id":"minecraft:glow_item_frame","localizedName":"Glow Item Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_item_frame"},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glow_lichen"},{"id":"minecraft:glow_squid_spawn_egg","localizedName":"Glow Squid Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glow_squid_spawn_egg"},{"id":"minecraft:glowstone","localizedName":"Glowstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.glowstone"},{"id":"minecraft:glowstone_dust","localizedName":"Glowstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.glowstone_dust"},{"id":"minecraft:goat_horn","localizedName":"Goat Horn","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.goat_horn"},{"id":"minecraft:goat_spawn_egg","localizedName":"Goat Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.goat_spawn_egg"},{"id":"minecraft:gold_block","localizedName":"Block of Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_block"},{"id":"minecraft:gold_ingot","localizedName":"Gold Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_ingot"},{"id":"minecraft:gold_nugget","localizedName":"Gold Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gold_nugget"},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gold_ore"},{"id":"minecraft:golden_apple","localizedName":"Golden Apple","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_apple"},{"id":"minecraft:golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_axe"},{"id":"minecraft:golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_boots"},{"id":"minecraft:golden_carrot","localizedName":"Golden Carrot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.golden_carrot"},{"id":"minecraft:golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_chestplate"},{"id":"minecraft:golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_helmet"},{"id":"minecraft:golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_hoe"},{"id":"minecraft:golden_horse_armor","localizedName":"Golden Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_horse_armor"},{"id":"minecraft:golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_leggings"},{"id":"minecraft:golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_pickaxe"},{"id":"minecraft:golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_shovel"},{"id":"minecraft:golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_sword"},{"id":"minecraft:granite","localizedName":"Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite"},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_slab"},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_stairs"},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.granite_wall"},{"id":"minecraft:grass","localizedName":"Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass"},{"id":"minecraft:grass_block","localizedName":"Grass Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grass_block"},{"id":"minecraft:gravel","localizedName":"Gravel","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gravel"},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.gray_banner"},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_bed"},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_candle"},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_carpet"},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete"},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete_powder"},{"id":"minecraft:gray_dye","localizedName":"Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gray_dye"},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_glazed_terracotta"},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.gray_shulker_box"},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass"},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass_pane"},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_terracotta"},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.gray_wool"},{"id":"minecraft:green_banner","localizedName":"Green Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.green_banner"},{"id":"minecraft:green_bed","localizedName":"Green Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_bed"},{"id":"minecraft:green_candle","localizedName":"Green Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_candle"},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_carpet"},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete"},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete_powder"},{"id":"minecraft:green_dye","localizedName":"Green Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.green_dye"},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_glazed_terracotta"},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.green_shulker_box"},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass"},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass_pane"},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_terracotta"},{"id":"minecraft:green_wool","localizedName":"Green Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.green_wool"},{"id":"minecraft:grindstone","localizedName":"Grindstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.grindstone"},{"id":"minecraft:guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.guardian_spawn_egg"},{"id":"minecraft:gunpowder","localizedName":"Gunpowder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.gunpowder"},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hanging_roots"},{"id":"minecraft:hay_block","localizedName":"Hay Bale","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hay_block"},{"id":"minecraft:heart_of_the_sea","localizedName":"Heart of the Sea","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.heart_of_the_sea"},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate"},{"id":"minecraft:hoglin_spawn_egg","localizedName":"Hoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.hoglin_spawn_egg"},{"id":"minecraft:honey_block","localizedName":"Honey Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honey_block"},{"id":"minecraft:honey_bottle","localizedName":"Honey Bottle","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.honey_bottle"},{"id":"minecraft:honeycomb","localizedName":"Honeycomb","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.honeycomb"},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.honeycomb_block"},{"id":"minecraft:hopper","localizedName":"Hopper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.hopper"},{"id":"minecraft:hopper_minecart","localizedName":"Minecart with Hopper","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.hopper_minecart"},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral"},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_block"},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_fan"},{"id":"minecraft:horse_spawn_egg","localizedName":"Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.horse_spawn_egg"},{"id":"minecraft:husk_spawn_egg","localizedName":"Husk Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.husk_spawn_egg"},{"id":"minecraft:ice","localizedName":"Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ice"},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks"},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cobblestone"},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cracked_stone_bricks"},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_deepslate"},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_mossy_stone_bricks"},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone"},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone_bricks"},{"id":"minecraft:ink_sac","localizedName":"Ink Sac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ink_sac"},{"id":"minecraft:iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_axe"},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_bars"},{"id":"minecraft:iron_block","localizedName":"Block of Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_block"},{"id":"minecraft:iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_boots"},{"id":"minecraft:iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_chestplate"},{"id":"minecraft:iron_door","localizedName":"Iron Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_door"},{"id":"minecraft:iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_helmet"},{"id":"minecraft:iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_hoe"},{"id":"minecraft:iron_horse_armor","localizedName":"Iron Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_horse_armor"},{"id":"minecraft:iron_ingot","localizedName":"Iron Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_ingot"},{"id":"minecraft:iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_leggings"},{"id":"minecraft:iron_nugget","localizedName":"Iron Nugget","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.iron_nugget"},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_ore"},{"id":"minecraft:iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_pickaxe"},{"id":"minecraft:iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_shovel"},{"id":"minecraft:iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_sword"},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.iron_trapdoor"},{"id":"minecraft:item_frame","localizedName":"Item Frame","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.item_frame"},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jack_o_lantern"},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jigsaw"},{"id":"minecraft:jukebox","localizedName":"Jukebox","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jukebox"},{"id":"minecraft:jungle_boat","localizedName":"Jungle Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_boat"},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_button"},{"id":"minecraft:jungle_chest_boat","localizedName":"Jungle Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_chest_boat"},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_door"},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence"},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence_gate"},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_leaves"},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_log"},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_planks"},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_pressure_plate"},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_sapling"},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_sign"},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_slab"},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_stairs"},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_trapdoor"},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_wood"},{"id":"minecraft:kelp","localizedName":"Kelp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.kelp"},{"id":"minecraft:knowledge_book","localizedName":"Knowledge Book","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.knowledge_book"},{"id":"minecraft:ladder","localizedName":"Ladder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ladder"},{"id":"minecraft:lantern","localizedName":"Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lantern"},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_block"},{"id":"minecraft:lapis_lazuli","localizedName":"Lapis Lazuli","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lapis_lazuli"},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_ore"},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.large_amethyst_bud"},{"id":"minecraft:large_fern","localizedName":"Large Fern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.large_fern"},{"id":"minecraft:lava_bucket","localizedName":"Lava Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lava_bucket"},{"id":"minecraft:lead","localizedName":"Lead","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lead"},{"id":"minecraft:leather","localizedName":"Leather","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.leather"},{"id":"minecraft:leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_boots"},{"id":"minecraft:leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_chestplate"},{"id":"minecraft:leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_helmet"},{"id":"minecraft:leather_horse_armor","localizedName":"Leather Horse Armor","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_horse_armor"},{"id":"minecraft:leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_leggings"},{"id":"minecraft:lectern","localizedName":"Lectern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lectern"},{"id":"minecraft:lever","localizedName":"Lever","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lever"},{"id":"minecraft:light","localizedName":"Light","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light"},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_blue_banner"},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_bed"},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_candle"},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_carpet"},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete"},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete_powder"},{"id":"minecraft:light_blue_dye","localizedName":"Light Blue Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_blue_dye"},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_glazed_terracotta"},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_shulker_box"},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass"},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass_pane"},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_terracotta"},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_wool"},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.light_gray_banner"},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_bed"},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_candle"},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_carpet"},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete"},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete_powder"},{"id":"minecraft:light_gray_dye","localizedName":"Light Gray Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.light_gray_dye"},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_glazed_terracotta"},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_shulker_box"},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass"},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass_pane"},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_terracotta"},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_wool"},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.light_weighted_pressure_plate"},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lightning_rod"},{"id":"minecraft:lilac","localizedName":"Lilac","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lilac"},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_of_the_valley"},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lily_pad"},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.lime_banner"},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_bed"},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_candle"},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_carpet"},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete"},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete_powder"},{"id":"minecraft:lime_dye","localizedName":"Lime Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.lime_dye"},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_glazed_terracotta"},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.lime_shulker_box"},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass"},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass_pane"},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_terracotta"},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lime_wool"},{"id":"minecraft:lingering_potion","localizedName":"Lingering Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.lingering_potion.effect.water"},{"id":"minecraft:llama_spawn_egg","localizedName":"Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.llama_spawn_egg"},{"id":"minecraft:lodestone","localizedName":"Lodestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.lodestone"},{"id":"minecraft:loom","localizedName":"Loom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.loom"},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.magenta_banner"},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_bed"},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_candle"},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_carpet"},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete"},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete_powder"},{"id":"minecraft:magenta_dye","localizedName":"Magenta Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magenta_dye"},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_glazed_terracotta"},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_shulker_box"},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass"},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass_pane"},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_terracotta"},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_wool"},{"id":"minecraft:magma_block","localizedName":"Magma Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.magma_block"},{"id":"minecraft:magma_cream","localizedName":"Magma Cream","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cream"},{"id":"minecraft:magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cube_spawn_egg"},{"id":"minecraft:mangrove_boat","localizedName":"Mangrove Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_boat"},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_button"},{"id":"minecraft:mangrove_chest_boat","localizedName":"Mangrove Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_chest_boat"},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_door"},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence"},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence_gate"},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_leaves"},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_log"},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_planks"},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_pressure_plate"},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_propagule"},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_roots"},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.mangrove_sign"},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_slab"},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_stairs"},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_trapdoor"},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_wood"},{"id":"minecraft:map","localizedName":"Empty Map","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.map"},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.medium_amethyst_bud"},{"id":"minecraft:melon","localizedName":"Melon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.melon"},{"id":"minecraft:melon_seeds","localizedName":"Melon Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_seeds"},{"id":"minecraft:melon_slice","localizedName":"Melon Slice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.melon_slice"},{"id":"minecraft:milk_bucket","localizedName":"Milk Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.milk_bucket"},{"id":"minecraft:minecart","localizedName":"Minecart","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.minecart"},{"id":"minecraft:mojang_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mojang_banner_pattern"},{"id":"minecraft:mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mooshroom_spawn_egg"},{"id":"minecraft:moss_block","localizedName":"Moss Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.moss_block"},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.moss_carpet"},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone"},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_slab"},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_stairs"},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_wall"},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_slab"},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_stairs"},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_wall"},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_bricks"},{"id":"minecraft:mud","localizedName":"Mud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mud"},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_slab"},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_stairs"},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_wall"},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mud_bricks"},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.muddy_mangrove_roots"},{"id":"minecraft:mule_spawn_egg","localizedName":"Mule Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mule_spawn_egg"},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mushroom_stem"},{"id":"minecraft:mushroom_stew","localizedName":"Mushroom Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.mushroom_stew"},{"id":"minecraft:music_disc_11","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_11"},{"id":"minecraft:music_disc_13","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_13"},{"id":"minecraft:music_disc_5","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_5"},{"id":"minecraft:music_disc_blocks","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_blocks"},{"id":"minecraft:music_disc_cat","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_cat"},{"id":"minecraft:music_disc_chirp","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_chirp"},{"id":"minecraft:music_disc_far","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_far"},{"id":"minecraft:music_disc_mall","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mall"},{"id":"minecraft:music_disc_mellohi","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mellohi"},{"id":"minecraft:music_disc_otherside","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_otherside"},{"id":"minecraft:music_disc_pigstep","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_pigstep"},{"id":"minecraft:music_disc_stal","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_stal"},{"id":"minecraft:music_disc_strad","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_strad"},{"id":"minecraft:music_disc_wait","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_wait"},{"id":"minecraft:music_disc_ward","localizedName":"Music Disc","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_ward"},{"id":"minecraft:mutton","localizedName":"Raw Mutton","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.mutton"},{"id":"minecraft:mycelium","localizedName":"Mycelium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.mycelium"},{"id":"minecraft:name_tag","localizedName":"Name Tag","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.name_tag"},{"id":"minecraft:nautilus_shell","localizedName":"Nautilus Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nautilus_shell"},{"id":"minecraft:nether_brick","localizedName":"Nether Brick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_brick"},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_fence"},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_slab"},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_stairs"},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_wall"},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_bricks"},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_gold_ore"},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_quartz_ore"},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_sprouts"},{"id":"minecraft:nether_star","localizedName":"Nether Star","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_star"},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.nether_wart"},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.nether_wart_block"},{"id":"minecraft:netherite_axe","localizedName":"Netherite Axe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_axe"},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherite_block"},{"id":"minecraft:netherite_boots","localizedName":"Netherite Boots","maxDamage":481,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_boots"},{"id":"minecraft:netherite_chestplate","localizedName":"Netherite Chestplate","maxDamage":592,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_chestplate"},{"id":"minecraft:netherite_helmet","localizedName":"Netherite Helmet","maxDamage":407,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_helmet"},{"id":"minecraft:netherite_hoe","localizedName":"Netherite Hoe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_hoe"},{"id":"minecraft:netherite_ingot","localizedName":"Netherite Ingot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_ingot"},{"id":"minecraft:netherite_leggings","localizedName":"Netherite Leggings","maxDamage":555,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_leggings"},{"id":"minecraft:netherite_pickaxe","localizedName":"Netherite Pickaxe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_pickaxe"},{"id":"minecraft:netherite_scrap","localizedName":"Netherite Scrap","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_scrap"},{"id":"minecraft:netherite_shovel","localizedName":"Netherite Shovel","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_shovel"},{"id":"minecraft:netherite_sword","localizedName":"Netherite Sword","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_sword"},{"id":"minecraft:netherrack","localizedName":"Netherrack","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.netherrack"},{"id":"minecraft:note_block","localizedName":"Note Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.note_block"},{"id":"minecraft:oak_boat","localizedName":"Oak Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.oak_boat"},{"id":"minecraft:oak_button","localizedName":"Oak Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_button"},{"id":"minecraft:oak_chest_boat","localizedName":"Oak Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.oak_chest_boat"},{"id":"minecraft:oak_door","localizedName":"Oak Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_door"},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence"},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence_gate"},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_leaves"},{"id":"minecraft:oak_log","localizedName":"Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_log"},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_planks"},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_pressure_plate"},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_sapling"},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.oak_sign"},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_slab"},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_stairs"},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_trapdoor"},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oak_wood"},{"id":"minecraft:observer","localizedName":"Observer","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.observer"},{"id":"minecraft:obsidian","localizedName":"Obsidian","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.obsidian"},{"id":"minecraft:ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ocelot_spawn_egg"},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.ochre_froglight"},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.orange_banner"},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_bed"},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_candle"},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_carpet"},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete"},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete_powder"},{"id":"minecraft:orange_dye","localizedName":"Orange Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.orange_dye"},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_glazed_terracotta"},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.orange_shulker_box"},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass"},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass_pane"},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_terracotta"},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_tulip"},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.orange_wool"},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxeye_daisy"},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper"},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper"},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_slab"},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_stairs"},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.packed_ice"},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.packed_mud"},{"id":"minecraft:painting","localizedName":"Painting","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.painting"},{"id":"minecraft:panda_spawn_egg","localizedName":"Panda Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.panda_spawn_egg"},{"id":"minecraft:paper","localizedName":"Paper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.paper"},{"id":"minecraft:parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.parrot_spawn_egg"},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pearlescent_froglight"},{"id":"minecraft:peony","localizedName":"Peony","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.peony"},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.petrified_oak_slab"},{"id":"minecraft:phantom_membrane","localizedName":"Phantom Membrane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_membrane"},{"id":"minecraft:phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_spawn_egg"},{"id":"minecraft:pig_spawn_egg","localizedName":"Pig Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pig_spawn_egg"},{"id":"minecraft:piglin_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.piglin_banner_pattern"},{"id":"minecraft:piglin_brute_spawn_egg","localizedName":"Piglin Brute Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_brute_spawn_egg"},{"id":"minecraft:piglin_spawn_egg","localizedName":"Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_spawn_egg"},{"id":"minecraft:pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pillager_spawn_egg"},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.pink_banner"},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_bed"},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_candle"},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_carpet"},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete"},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete_powder"},{"id":"minecraft:pink_dye","localizedName":"Pink Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pink_dye"},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_glazed_terracotta"},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.pink_shulker_box"},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass"},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass_pane"},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_terracotta"},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_tulip"},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pink_wool"},{"id":"minecraft:piston","localizedName":"Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.piston"},{"id":"minecraft:player_head","localizedName":"Player Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.player_head"},{"id":"minecraft:podzol","localizedName":"Podzol","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.podzol"},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pointed_dripstone"},{"id":"minecraft:poisonous_potato","localizedName":"Poisonous Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.poisonous_potato"},{"id":"minecraft:polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.polar_bear_spawn_egg"},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite"},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_slab"},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_stairs"},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_basalt"},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone"},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_slab"},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_stairs"},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_wall"},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_bricks"},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_button"},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_pressure_plate"},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_slab"},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_stairs"},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_wall"},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate"},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_slab"},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_stairs"},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_wall"},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite"},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_slab"},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_stairs"},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite"},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_slab"},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_stairs"},{"id":"minecraft:popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.popped_chorus_fruit"},{"id":"minecraft:poppy","localizedName":"Poppy","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.poppy"},{"id":"minecraft:porkchop","localizedName":"Raw Porkchop","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.porkchop"},{"id":"minecraft:potato","localizedName":"Potato","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.potato"},{"id":"minecraft:potion","localizedName":"Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.potion.effect.water"},{"id":"minecraft:powder_snow_bucket","localizedName":"Powder Snow Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.powder_snow_bucket"},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.powered_rail"},{"id":"minecraft:prismarine","localizedName":"Prismarine","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine"},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_slab"},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_stairs"},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_bricks"},{"id":"minecraft:prismarine_crystals","localizedName":"Prismarine Crystals","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_crystals"},{"id":"minecraft:prismarine_shard","localizedName":"Prismarine Shard","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_shard"},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_slab"},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_stairs"},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_wall"},{"id":"minecraft:pufferfish","localizedName":"Pufferfish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish"},{"id":"minecraft:pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.pufferfish_bucket"},{"id":"minecraft:pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish_spawn_egg"},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.pumpkin"},{"id":"minecraft:pumpkin_pie","localizedName":"Pumpkin Pie","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_pie"},{"id":"minecraft:pumpkin_seeds","localizedName":"Pumpkin Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_seeds"},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.purple_banner"},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_bed"},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_candle"},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_carpet"},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete"},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete_powder"},{"id":"minecraft:purple_dye","localizedName":"Purple Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.purple_dye"},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_glazed_terracotta"},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.purple_shulker_box"},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass"},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass_pane"},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_terracotta"},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purple_wool"},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_block"},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_pillar"},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_slab"},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_stairs"},{"id":"minecraft:quartz","localizedName":"Nether Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.quartz"},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_block"},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_bricks"},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_pillar"},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_slab"},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_stairs"},{"id":"minecraft:rabbit","localizedName":"Raw Rabbit","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit"},{"id":"minecraft:rabbit_foot","localizedName":"Rabbit\u0027s Foot","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_foot"},{"id":"minecraft:rabbit_hide","localizedName":"Rabbit Hide","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_hide"},{"id":"minecraft:rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_spawn_egg"},{"id":"minecraft:rabbit_stew","localizedName":"Rabbit Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.rabbit_stew"},{"id":"minecraft:rail","localizedName":"Rail","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rail"},{"id":"minecraft:ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.ravager_spawn_egg"},{"id":"minecraft:raw_copper","localizedName":"Raw Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_copper"},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_copper_block"},{"id":"minecraft:raw_gold","localizedName":"Raw Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_gold"},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_gold_block"},{"id":"minecraft:raw_iron","localizedName":"Raw Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.raw_iron"},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.raw_iron_block"},{"id":"minecraft:recovery_compass","localizedName":"Recovery Compass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.recovery_compass"},{"id":"minecraft:red_banner","localizedName":"Red Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.red_banner"},{"id":"minecraft:red_bed","localizedName":"Red Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_bed"},{"id":"minecraft:red_candle","localizedName":"Red Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_candle"},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_carpet"},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete"},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete_powder"},{"id":"minecraft:red_dye","localizedName":"Red Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.red_dye"},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_glazed_terracotta"},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom"},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom_block"},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_slab"},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_stairs"},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_wall"},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_bricks"},{"id":"minecraft:red_sand","localizedName":"Red Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sand"},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone"},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_slab"},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_stairs"},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_wall"},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.red_shulker_box"},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass"},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass_pane"},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_terracotta"},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_tulip"},{"id":"minecraft:red_wool","localizedName":"Red Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.red_wool"},{"id":"minecraft:redstone","localizedName":"Redstone Dust","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.redstone"},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_block"},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_lamp"},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_ore"},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_torch"},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.reinforced_deepslate"},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeater"},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.repeating_command_block"},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.respawn_anchor"},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rooted_dirt"},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.rose_bush"},{"id":"minecraft:rotten_flesh","localizedName":"Rotten Flesh","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.rotten_flesh"},{"id":"minecraft:saddle","localizedName":"Saddle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.saddle"},{"id":"minecraft:salmon","localizedName":"Raw Salmon","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon"},{"id":"minecraft:salmon_bucket","localizedName":"Bucket of Salmon","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.salmon_bucket"},{"id":"minecraft:salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.salmon_spawn_egg"},{"id":"minecraft:sand","localizedName":"Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sand"},{"id":"minecraft:sandstone","localizedName":"Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone"},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_slab"},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_stairs"},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_wall"},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.scaffolding"},{"id":"minecraft:sculk","localizedName":"Sculk","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk"},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_catalyst"},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_sensor"},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_shrieker"},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_vein"},{"id":"minecraft:scute","localizedName":"Scute","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.scute"},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_lantern"},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sea_pickle"},{"id":"minecraft:seagrass","localizedName":"Seagrass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.seagrass"},{"id":"minecraft:shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1,"unlocalizedName":"item.minecraft.shears"},{"id":"minecraft:sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sheep_spawn_egg"},{"id":"minecraft:shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1,"unlocalizedName":"item.minecraft.shield"},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.shroomlight"},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.shulker_box"},{"id":"minecraft:shulker_shell","localizedName":"Shulker Shell","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_shell"},{"id":"minecraft:shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_spawn_egg"},{"id":"minecraft:silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.silverfish_spawn_egg"},{"id":"minecraft:skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg"},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.skeleton_skull"},{"id":"minecraft:skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_spawn_egg"},{"id":"minecraft:skull_banner_pattern","localizedName":"Banner Pattern","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.skull_banner_pattern"},{"id":"minecraft:slime_ball","localizedName":"Slimeball","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_ball"},{"id":"minecraft:slime_block","localizedName":"Slime Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.slime_block"},{"id":"minecraft:slime_spawn_egg","localizedName":"Slime Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.slime_spawn_egg"},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.small_amethyst_bud"},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.small_dripleaf"},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smithing_table"},{"id":"minecraft:smoker","localizedName":"Smoker","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smoker"},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_basalt"},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz"},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_slab"},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_stairs"},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone"},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_slab"},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs"},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone"},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_slab"},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_stairs"},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone"},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone_slab"},{"id":"minecraft:snow","localizedName":"Snow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow"},{"id":"minecraft:snow_block","localizedName":"Snow Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.snow_block"},{"id":"minecraft:snowball","localizedName":"Snowball","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.snowball"},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_campfire"},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_lantern"},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_sand"},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_soil"},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.soul_torch"},{"id":"minecraft:spawner","localizedName":"Spawner","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spawner"},{"id":"minecraft:spectral_arrow","localizedName":"Spectral Arrow","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spectral_arrow"},{"id":"minecraft:spider_eye","localizedName":"Spider Eye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_eye"},{"id":"minecraft:spider_spawn_egg","localizedName":"Spider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.spider_spawn_egg"},{"id":"minecraft:splash_potion","localizedName":"Splash Water Bottle","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.splash_potion.effect.water"},{"id":"minecraft:sponge","localizedName":"Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sponge"},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spore_blossom"},{"id":"minecraft:spruce_boat","localizedName":"Spruce Boat","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_boat"},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_button"},{"id":"minecraft:spruce_chest_boat","localizedName":"Spruce Boat with Chest","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_chest_boat"},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_door"},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence"},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence_gate"},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_leaves"},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_log"},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_planks"},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_pressure_plate"},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_sapling"},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_sign"},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_slab"},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_stairs"},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_trapdoor"},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_wood"},{"id":"minecraft:spyglass","localizedName":"Spyglass","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.spyglass"},{"id":"minecraft:squid_spawn_egg","localizedName":"Squid Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.squid_spawn_egg"},{"id":"minecraft:stick","localizedName":"Stick","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stick"},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sticky_piston"},{"id":"minecraft:stone","localizedName":"Stone","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone"},{"id":"minecraft:stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_axe"},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_slab"},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_stairs"},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_wall"},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_bricks"},{"id":"minecraft:stone_button","localizedName":"Stone Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_button"},{"id":"minecraft:stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_hoe"},{"id":"minecraft:stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_pickaxe"},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_pressure_plate"},{"id":"minecraft:stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_shovel"},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_slab"},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stone_stairs"},{"id":"minecraft:stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_sword"},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stonecutter"},{"id":"minecraft:stray_spawn_egg","localizedName":"Stray Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.stray_spawn_egg"},{"id":"minecraft:strider_spawn_egg","localizedName":"Strider Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.strider_spawn_egg"},{"id":"minecraft:string","localizedName":"String","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.string"},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_log"},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_wood"},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_log"},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_wood"},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_hyphae"},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_stem"},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_log"},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_wood"},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_log"},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_wood"},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_log"},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_wood"},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_log"},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_wood"},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_log"},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_wood"},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_hyphae"},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_stem"},{"id":"minecraft:structure_block","localizedName":"Structure Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_block"},{"id":"minecraft:structure_void","localizedName":"Structure Void","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.structure_void"},{"id":"minecraft:sugar","localizedName":"Sugar","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sugar"},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sugar_cane"},{"id":"minecraft:sunflower","localizedName":"Sunflower","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.sunflower"},{"id":"minecraft:suspicious_stew","localizedName":"Suspicious Stew","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.suspicious_stew"},{"id":"minecraft:sweet_berries","localizedName":"Sweet Berries","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.sweet_berries"},{"id":"minecraft:tadpole_bucket","localizedName":"Bucket of Tadpole","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tadpole_bucket"},{"id":"minecraft:tadpole_spawn_egg","localizedName":"Tadpole Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tadpole_spawn_egg"},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tall_grass"},{"id":"minecraft:target","localizedName":"Target","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.target"},{"id":"minecraft:terracotta","localizedName":"Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.terracotta"},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tinted_glass"},{"id":"minecraft:tipped_arrow","localizedName":"Arrow of Poison","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tipped_arrow.effect.poison"},{"id":"minecraft:tnt","localizedName":"TNT","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tnt"},{"id":"minecraft:tnt_minecart","localizedName":"Minecart with TNT","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tnt_minecart"},{"id":"minecraft:torch","localizedName":"Torch","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.torch"},{"id":"minecraft:totem_of_undying","localizedName":"Totem of Undying","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.totem_of_undying"},{"id":"minecraft:trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.trader_llama_spawn_egg"},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.trapped_chest"},{"id":"minecraft:trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.trident"},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tripwire_hook"},{"id":"minecraft:tropical_fish","localizedName":"Tropical Fish","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish"},{"id":"minecraft:tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.tropical_fish_bucket"},{"id":"minecraft:tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish_spawn_egg"},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral"},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_block"},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_fan"},{"id":"minecraft:tuff","localizedName":"Tuff","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.tuff"},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.turtle_egg"},{"id":"minecraft:turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1,"unlocalizedName":"item.minecraft.turtle_helmet"},{"id":"minecraft:turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_spawn_egg"},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.twisting_vines"},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.verdant_froglight"},{"id":"minecraft:vex_spawn_egg","localizedName":"Vex Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vex_spawn_egg"},{"id":"minecraft:villager_spawn_egg","localizedName":"Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.villager_spawn_egg"},{"id":"minecraft:vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.vindicator_spawn_egg"},{"id":"minecraft:vine","localizedName":"Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.vine"},{"id":"minecraft:wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wandering_trader_spawn_egg"},{"id":"minecraft:warden_spawn_egg","localizedName":"Warden Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.warden_spawn_egg"},{"id":"minecraft:warped_button","localizedName":"Warped Button","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_button"},{"id":"minecraft:warped_door","localizedName":"Warped Door","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_door"},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence"},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence_gate"},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fungus"},{"id":"minecraft:warped_fungus_on_a_stick","localizedName":"Warped Fungus on a Stick","maxDamage":100,"maxStackSize":1,"unlocalizedName":"item.minecraft.warped_fungus_on_a_stick"},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_hyphae"},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_nylium"},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_planks"},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_pressure_plate"},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_roots"},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.warped_sign"},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_slab"},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stairs"},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stem"},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_trapdoor"},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.warped_wart_block"},{"id":"minecraft:water_bucket","localizedName":"Water Bucket","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.water_bucket"},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_block"},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper"},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_slab"},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_stairs"},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper"},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper"},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_slab"},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_stairs"},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper"},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper"},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_slab"},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_stairs"},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper"},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper"},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_slab"},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_stairs"},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper"},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper"},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_slab"},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_stairs"},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.weeping_vines"},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wet_sponge"},{"id":"minecraft:wheat","localizedName":"Wheat","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat"},{"id":"minecraft:wheat_seeds","localizedName":"Wheat Seeds","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wheat_seeds"},{"id":"minecraft:white_banner","localizedName":"White Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.white_banner"},{"id":"minecraft:white_bed","localizedName":"White Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_bed"},{"id":"minecraft:white_candle","localizedName":"White Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_candle"},{"id":"minecraft:white_carpet","localizedName":"White Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_carpet"},{"id":"minecraft:white_concrete","localizedName":"White Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete"},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete_powder"},{"id":"minecraft:white_dye","localizedName":"White Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.white_dye"},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_glazed_terracotta"},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.white_shulker_box"},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass"},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass_pane"},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_terracotta"},{"id":"minecraft:white_tulip","localizedName":"White Tulip","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_tulip"},{"id":"minecraft:white_wool","localizedName":"White Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.white_wool"},{"id":"minecraft:witch_spawn_egg","localizedName":"Witch Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.witch_spawn_egg"},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_rose"},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.wither_skeleton_skull"},{"id":"minecraft:wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg"},{"id":"minecraft:wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.wolf_spawn_egg"},{"id":"minecraft:wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_axe"},{"id":"minecraft:wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_hoe"},{"id":"minecraft:wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_pickaxe"},{"id":"minecraft:wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_shovel"},{"id":"minecraft:wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_sword"},{"id":"minecraft:writable_book","localizedName":"Book and Quill","maxDamage":0,"maxStackSize":1,"unlocalizedName":"item.minecraft.writable_book"},{"id":"minecraft:written_book","localizedName":"Written Book","maxDamage":0,"maxStackSize":16,"unlocalizedName":"item.minecraft.written_book"},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","maxDamage":0,"maxStackSize":16,"unlocalizedName":"block.minecraft.yellow_banner"},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_bed"},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_candle"},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_carpet"},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete"},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete_powder"},{"id":"minecraft:yellow_dye","localizedName":"Yellow Dye","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.yellow_dye"},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_glazed_terracotta"},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","maxDamage":0,"maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_shulker_box"},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass"},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass_pane"},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_terracotta"},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_wool"},{"id":"minecraft:zoglin_spawn_egg","localizedName":"Zoglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zoglin_spawn_egg"},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","maxDamage":0,"maxStackSize":64,"unlocalizedName":"block.minecraft.zombie_head"},{"id":"minecraft:zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_horse_spawn_egg"},{"id":"minecraft:zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_spawn_egg"},{"id":"minecraft:zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_villager_spawn_egg"},{"id":"minecraft:zombified_piglin_spawn_egg","localizedName":"Zombified Piglin Spawn Egg","maxDamage":0,"maxStackSize":64,"unlocalizedName":"item.minecraft.zombified_piglin_spawn_egg"}] diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.121.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.121.json new file mode 100644 index 000000000..aad491aa1 --- /dev/null +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.121.json @@ -0,0 +1 @@ +[{"id":"minecraft:acacia_boat","localizedName":"Acacia Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_boat"},{"id":"minecraft:acacia_button","localizedName":"Acacia Button","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_button"},{"id":"minecraft:acacia_chest_boat","localizedName":"Acacia Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_chest_boat"},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_door"},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence"},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence_gate"},{"id":"minecraft:acacia_hanging_sign","localizedName":"Acacia Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_hanging_sign"},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_leaves"},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_log"},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_planks"},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_pressure_plate"},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_sapling"},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_sign"},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_slab"},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_stairs"},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_trapdoor"},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_wood"},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.activator_rail"},{"id":"minecraft:air","localizedName":"Air","maxStackSize":64,"unlocalizedName":"block.minecraft.air"},{"id":"minecraft:allay_spawn_egg","localizedName":"Allay Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.allay_spawn_egg"},{"id":"minecraft:allium","localizedName":"Allium","maxStackSize":64,"unlocalizedName":"block.minecraft.allium"},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_block"},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_cluster"},{"id":"minecraft:amethyst_shard","localizedName":"Amethyst Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.amethyst_shard"},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","maxStackSize":64,"unlocalizedName":"block.minecraft.ancient_debris"},{"id":"minecraft:andesite","localizedName":"Andesite","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite"},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_slab"},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_stairs"},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_wall"},{"id":"minecraft:angler_pottery_sherd","localizedName":"Angler Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.angler_pottery_sherd"},{"id":"minecraft:anvil","localizedName":"Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.anvil"},{"id":"minecraft:apple","localizedName":"Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.apple"},{"id":"minecraft:archer_pottery_sherd","localizedName":"Archer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.archer_pottery_sherd"},{"id":"minecraft:armadillo_scute","localizedName":"Armadillo Scute","maxStackSize":64,"unlocalizedName":"item.minecraft.armadillo_scute"},{"id":"minecraft:armadillo_spawn_egg","localizedName":"Armadillo Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.armadillo_spawn_egg"},{"id":"minecraft:armor_stand","localizedName":"Armor Stand","maxStackSize":16,"unlocalizedName":"item.minecraft.armor_stand"},{"id":"minecraft:arms_up_pottery_sherd","localizedName":"Arms Up Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.arms_up_pottery_sherd"},{"id":"minecraft:arrow","localizedName":"Arrow","maxStackSize":64,"unlocalizedName":"item.minecraft.arrow"},{"id":"minecraft:axolotl_bucket","localizedName":"Bucket of Axolotl","maxStackSize":1,"unlocalizedName":"item.minecraft.axolotl_bucket"},{"id":"minecraft:axolotl_spawn_egg","localizedName":"Axolotl Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.axolotl_spawn_egg"},{"id":"minecraft:azalea","localizedName":"Azalea","maxStackSize":64,"unlocalizedName":"block.minecraft.azalea"},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.azalea_leaves"},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","maxStackSize":64,"unlocalizedName":"block.minecraft.azure_bluet"},{"id":"minecraft:baked_potato","localizedName":"Baked Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.baked_potato"},{"id":"minecraft:bamboo","localizedName":"Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo"},{"id":"minecraft:bamboo_block","localizedName":"Block of Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_block"},{"id":"minecraft:bamboo_button","localizedName":"Bamboo Button","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_button"},{"id":"minecraft:bamboo_chest_raft","localizedName":"Bamboo Raft with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.bamboo_chest_raft"},{"id":"minecraft:bamboo_door","localizedName":"Bamboo Door","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_door"},{"id":"minecraft:bamboo_fence","localizedName":"Bamboo Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_fence"},{"id":"minecraft:bamboo_fence_gate","localizedName":"Bamboo Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_fence_gate"},{"id":"minecraft:bamboo_hanging_sign","localizedName":"Bamboo Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.bamboo_hanging_sign"},{"id":"minecraft:bamboo_mosaic","localizedName":"Bamboo Mosaic","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic"},{"id":"minecraft:bamboo_mosaic_slab","localizedName":"Bamboo Mosaic Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic_slab"},{"id":"minecraft:bamboo_mosaic_stairs","localizedName":"Bamboo Mosaic Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic_stairs"},{"id":"minecraft:bamboo_planks","localizedName":"Bamboo Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_planks"},{"id":"minecraft:bamboo_pressure_plate","localizedName":"Bamboo Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_pressure_plate"},{"id":"minecraft:bamboo_raft","localizedName":"Bamboo Raft","maxStackSize":1,"unlocalizedName":"item.minecraft.bamboo_raft"},{"id":"minecraft:bamboo_sign","localizedName":"Bamboo Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.bamboo_sign"},{"id":"minecraft:bamboo_slab","localizedName":"Bamboo Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_slab"},{"id":"minecraft:bamboo_stairs","localizedName":"Bamboo Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_stairs"},{"id":"minecraft:bamboo_trapdoor","localizedName":"Bamboo Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_trapdoor"},{"id":"minecraft:barrel","localizedName":"Barrel","maxStackSize":64,"unlocalizedName":"block.minecraft.barrel"},{"id":"minecraft:barrier","localizedName":"Barrier","maxStackSize":64,"unlocalizedName":"block.minecraft.barrier"},{"id":"minecraft:basalt","localizedName":"Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.basalt"},{"id":"minecraft:bat_spawn_egg","localizedName":"Bat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bat_spawn_egg"},{"id":"minecraft:beacon","localizedName":"Beacon","maxStackSize":64,"unlocalizedName":"block.minecraft.beacon"},{"id":"minecraft:bedrock","localizedName":"Bedrock","maxStackSize":64,"unlocalizedName":"block.minecraft.bedrock"},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","maxStackSize":64,"unlocalizedName":"block.minecraft.bee_nest"},{"id":"minecraft:bee_spawn_egg","localizedName":"Bee Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bee_spawn_egg"},{"id":"minecraft:beef","localizedName":"Raw Beef","maxStackSize":64,"unlocalizedName":"item.minecraft.beef"},{"id":"minecraft:beehive","localizedName":"Beehive","maxStackSize":64,"unlocalizedName":"block.minecraft.beehive"},{"id":"minecraft:beetroot","localizedName":"Beetroot","maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot"},{"id":"minecraft:beetroot_seeds","localizedName":"Beetroot Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot_seeds"},{"id":"minecraft:beetroot_soup","localizedName":"Beetroot Soup","maxStackSize":1,"unlocalizedName":"item.minecraft.beetroot_soup"},{"id":"minecraft:bell","localizedName":"Bell","maxStackSize":64,"unlocalizedName":"block.minecraft.bell"},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","maxStackSize":64,"unlocalizedName":"block.minecraft.big_dripleaf"},{"id":"minecraft:birch_boat","localizedName":"Birch Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.birch_boat"},{"id":"minecraft:birch_button","localizedName":"Birch Button","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_button"},{"id":"minecraft:birch_chest_boat","localizedName":"Birch Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.birch_chest_boat"},{"id":"minecraft:birch_door","localizedName":"Birch Door","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_door"},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence"},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence_gate"},{"id":"minecraft:birch_hanging_sign","localizedName":"Birch Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.birch_hanging_sign"},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_leaves"},{"id":"minecraft:birch_log","localizedName":"Birch Log","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_log"},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_planks"},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_pressure_plate"},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_sapling"},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.birch_sign"},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_slab"},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_stairs"},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_trapdoor"},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_wood"},{"id":"minecraft:black_banner","localizedName":"Black Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.black_banner"},{"id":"minecraft:black_bed","localizedName":"Black Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.black_bed"},{"id":"minecraft:black_candle","localizedName":"Black Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.black_candle"},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.black_carpet"},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete"},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete_powder"},{"id":"minecraft:black_dye","localizedName":"Black Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.black_dye"},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.black_glazed_terracotta"},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.black_shulker_box"},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass"},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass_pane"},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.black_terracotta"},{"id":"minecraft:black_wool","localizedName":"Black Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.black_wool"},{"id":"minecraft:blackstone","localizedName":"Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone"},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_slab"},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_stairs"},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_wall"},{"id":"minecraft:blade_pottery_sherd","localizedName":"Blade Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.blade_pottery_sherd"},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","maxStackSize":64,"unlocalizedName":"block.minecraft.blast_furnace"},{"id":"minecraft:blaze_powder","localizedName":"Blaze Powder","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_powder"},{"id":"minecraft:blaze_rod","localizedName":"Blaze Rod","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_rod"},{"id":"minecraft:blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_spawn_egg"},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.blue_banner"},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.blue_bed"},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_candle"},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_carpet"},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete"},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete_powder"},{"id":"minecraft:blue_dye","localizedName":"Blue Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.blue_dye"},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_glazed_terracotta"},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_ice"},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_orchid"},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.blue_shulker_box"},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass"},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass_pane"},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_terracotta"},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_wool"},{"id":"minecraft:bogged_spawn_egg","localizedName":"Bogged Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bogged_spawn_egg"},{"id":"minecraft:bolt_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.bolt_armor_trim_smithing_template"},{"id":"minecraft:bone","localizedName":"Bone","maxStackSize":64,"unlocalizedName":"item.minecraft.bone"},{"id":"minecraft:bone_block","localizedName":"Bone Block","maxStackSize":64,"unlocalizedName":"block.minecraft.bone_block"},{"id":"minecraft:bone_meal","localizedName":"Bone Meal","maxStackSize":64,"unlocalizedName":"item.minecraft.bone_meal"},{"id":"minecraft:book","localizedName":"Book","maxStackSize":64,"unlocalizedName":"item.minecraft.book"},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","maxStackSize":64,"unlocalizedName":"block.minecraft.bookshelf"},{"id":"minecraft:bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1,"unlocalizedName":"item.minecraft.bow"},{"id":"minecraft:bowl","localizedName":"Bowl","maxStackSize":64,"unlocalizedName":"item.minecraft.bowl"},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral"},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_block"},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_fan"},{"id":"minecraft:bread","localizedName":"Bread","maxStackSize":64,"unlocalizedName":"item.minecraft.bread"},{"id":"minecraft:breeze_rod","localizedName":"Breeze Rod","maxStackSize":64,"unlocalizedName":"item.minecraft.breeze_rod"},{"id":"minecraft:breeze_spawn_egg","localizedName":"Breeze Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.breeze_spawn_egg"},{"id":"minecraft:brewer_pottery_sherd","localizedName":"Brewer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.brewer_pottery_sherd"},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","maxStackSize":64,"unlocalizedName":"block.minecraft.brewing_stand"},{"id":"minecraft:brick","localizedName":"Brick","maxStackSize":64,"unlocalizedName":"item.minecraft.brick"},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_slab"},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_stairs"},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_wall"},{"id":"minecraft:bricks","localizedName":"Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.bricks"},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.brown_banner"},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.brown_bed"},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_candle"},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_carpet"},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete"},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete_powder"},{"id":"minecraft:brown_dye","localizedName":"Brown Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.brown_dye"},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_glazed_terracotta"},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom"},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom_block"},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.brown_shulker_box"},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass"},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass_pane"},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_terracotta"},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_wool"},{"id":"minecraft:brush","localizedName":"Brush","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.brush"},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral"},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_block"},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_fan"},{"id":"minecraft:bucket","localizedName":"Bucket","maxStackSize":16,"unlocalizedName":"item.minecraft.bucket"},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","maxStackSize":64,"unlocalizedName":"block.minecraft.budding_amethyst"},{"id":"minecraft:bundle","localizedName":"Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.bundle"},{"id":"minecraft:burn_pottery_sherd","localizedName":"Burn Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.burn_pottery_sherd"},{"id":"minecraft:cactus","localizedName":"Cactus","maxStackSize":64,"unlocalizedName":"block.minecraft.cactus"},{"id":"minecraft:cake","localizedName":"Cake","maxStackSize":1,"unlocalizedName":"block.minecraft.cake"},{"id":"minecraft:calcite","localizedName":"Calcite","maxStackSize":64,"unlocalizedName":"block.minecraft.calcite"},{"id":"minecraft:calibrated_sculk_sensor","localizedName":"Calibrated Sculk Sensor","maxStackSize":64,"unlocalizedName":"block.minecraft.calibrated_sculk_sensor"},{"id":"minecraft:camel_spawn_egg","localizedName":"Camel Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.camel_spawn_egg"},{"id":"minecraft:campfire","localizedName":"Campfire","maxStackSize":64,"unlocalizedName":"block.minecraft.campfire"},{"id":"minecraft:candle","localizedName":"Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.candle"},{"id":"minecraft:carrot","localizedName":"Carrot","maxStackSize":64,"unlocalizedName":"item.minecraft.carrot"},{"id":"minecraft:carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1,"unlocalizedName":"item.minecraft.carrot_on_a_stick"},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","maxStackSize":64,"unlocalizedName":"block.minecraft.cartography_table"},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","maxStackSize":64,"unlocalizedName":"block.minecraft.carved_pumpkin"},{"id":"minecraft:cat_spawn_egg","localizedName":"Cat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cat_spawn_egg"},{"id":"minecraft:cauldron","localizedName":"Cauldron","maxStackSize":64,"unlocalizedName":"block.minecraft.cauldron"},{"id":"minecraft:cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cave_spider_spawn_egg"},{"id":"minecraft:chain","localizedName":"Chain","maxStackSize":64,"unlocalizedName":"block.minecraft.chain"},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.chain_command_block"},{"id":"minecraft:chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_boots"},{"id":"minecraft:chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_chestplate"},{"id":"minecraft:chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_helmet"},{"id":"minecraft:chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_leggings"},{"id":"minecraft:charcoal","localizedName":"Charcoal","maxStackSize":64,"unlocalizedName":"item.minecraft.charcoal"},{"id":"minecraft:cherry_boat","localizedName":"Cherry Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.cherry_boat"},{"id":"minecraft:cherry_button","localizedName":"Cherry Button","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_button"},{"id":"minecraft:cherry_chest_boat","localizedName":"Cherry Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.cherry_chest_boat"},{"id":"minecraft:cherry_door","localizedName":"Cherry Door","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_door"},{"id":"minecraft:cherry_fence","localizedName":"Cherry Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_fence"},{"id":"minecraft:cherry_fence_gate","localizedName":"Cherry Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_fence_gate"},{"id":"minecraft:cherry_hanging_sign","localizedName":"Cherry Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.cherry_hanging_sign"},{"id":"minecraft:cherry_leaves","localizedName":"Cherry Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_leaves"},{"id":"minecraft:cherry_log","localizedName":"Cherry Log","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_log"},{"id":"minecraft:cherry_planks","localizedName":"Cherry Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_planks"},{"id":"minecraft:cherry_pressure_plate","localizedName":"Cherry Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_pressure_plate"},{"id":"minecraft:cherry_sapling","localizedName":"Cherry Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_sapling"},{"id":"minecraft:cherry_sign","localizedName":"Cherry Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.cherry_sign"},{"id":"minecraft:cherry_slab","localizedName":"Cherry Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_slab"},{"id":"minecraft:cherry_stairs","localizedName":"Cherry Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_stairs"},{"id":"minecraft:cherry_trapdoor","localizedName":"Cherry Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_trapdoor"},{"id":"minecraft:cherry_wood","localizedName":"Cherry Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_wood"},{"id":"minecraft:chest","localizedName":"Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.chest"},{"id":"minecraft:chest_minecart","localizedName":"Minecart with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.chest_minecart"},{"id":"minecraft:chicken","localizedName":"Raw Chicken","maxStackSize":64,"unlocalizedName":"item.minecraft.chicken"},{"id":"minecraft:chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.chicken_spawn_egg"},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.chipped_anvil"},{"id":"minecraft:chiseled_bookshelf","localizedName":"Chiseled Bookshelf","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_bookshelf"},{"id":"minecraft:chiseled_copper","localizedName":"Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_copper"},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_deepslate"},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_nether_bricks"},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_polished_blackstone"},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_quartz_block"},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_red_sandstone"},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_sandstone"},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_stone_bricks"},{"id":"minecraft:chiseled_tuff","localizedName":"Chiseled Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_tuff"},{"id":"minecraft:chiseled_tuff_bricks","localizedName":"Chiseled Tuff Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_tuff_bricks"},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_flower"},{"id":"minecraft:chorus_fruit","localizedName":"Chorus Fruit","maxStackSize":64,"unlocalizedName":"item.minecraft.chorus_fruit"},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_plant"},{"id":"minecraft:clay","localizedName":"Clay","maxStackSize":64,"unlocalizedName":"block.minecraft.clay"},{"id":"minecraft:clay_ball","localizedName":"Clay Ball","maxStackSize":64,"unlocalizedName":"item.minecraft.clay_ball"},{"id":"minecraft:clock","localizedName":"Clock","maxStackSize":64,"unlocalizedName":"item.minecraft.clock"},{"id":"minecraft:coal","localizedName":"Coal","maxStackSize":64,"unlocalizedName":"item.minecraft.coal"},{"id":"minecraft:coal_block","localizedName":"Block of Coal","maxStackSize":64,"unlocalizedName":"block.minecraft.coal_block"},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.coal_ore"},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.coarse_dirt"},{"id":"minecraft:coast_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.coast_armor_trim_smithing_template"},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate"},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_slab"},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_stairs"},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_wall"},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone"},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_slab"},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_stairs"},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_wall"},{"id":"minecraft:cobweb","localizedName":"Cobweb","maxStackSize":64,"unlocalizedName":"block.minecraft.cobweb"},{"id":"minecraft:cocoa_beans","localizedName":"Cocoa Beans","maxStackSize":64,"unlocalizedName":"item.minecraft.cocoa_beans"},{"id":"minecraft:cod","localizedName":"Raw Cod","maxStackSize":64,"unlocalizedName":"item.minecraft.cod"},{"id":"minecraft:cod_bucket","localizedName":"Bucket of Cod","maxStackSize":1,"unlocalizedName":"item.minecraft.cod_bucket"},{"id":"minecraft:cod_spawn_egg","localizedName":"Cod Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cod_spawn_egg"},{"id":"minecraft:command_block","localizedName":"Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.command_block"},{"id":"minecraft:command_block_minecart","localizedName":"Minecart with Command Block","maxStackSize":1,"unlocalizedName":"item.minecraft.command_block_minecart"},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","maxStackSize":64,"unlocalizedName":"block.minecraft.comparator"},{"id":"minecraft:compass","localizedName":"Compass","maxStackSize":64,"unlocalizedName":"item.minecraft.compass"},{"id":"minecraft:composter","localizedName":"Composter","maxStackSize":64,"unlocalizedName":"block.minecraft.composter"},{"id":"minecraft:conduit","localizedName":"Conduit","maxStackSize":64,"unlocalizedName":"block.minecraft.conduit"},{"id":"minecraft:cooked_beef","localizedName":"Steak","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_beef"},{"id":"minecraft:cooked_chicken","localizedName":"Cooked Chicken","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_chicken"},{"id":"minecraft:cooked_cod","localizedName":"Cooked Cod","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_cod"},{"id":"minecraft:cooked_mutton","localizedName":"Cooked Mutton","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_mutton"},{"id":"minecraft:cooked_porkchop","localizedName":"Cooked Porkchop","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_porkchop"},{"id":"minecraft:cooked_rabbit","localizedName":"Cooked Rabbit","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_rabbit"},{"id":"minecraft:cooked_salmon","localizedName":"Cooked Salmon","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_salmon"},{"id":"minecraft:cookie","localizedName":"Cookie","maxStackSize":64,"unlocalizedName":"item.minecraft.cookie"},{"id":"minecraft:copper_block","localizedName":"Block of Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_block"},{"id":"minecraft:copper_bulb","localizedName":"Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_bulb"},{"id":"minecraft:copper_door","localizedName":"Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_door"},{"id":"minecraft:copper_grate","localizedName":"Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_grate"},{"id":"minecraft:copper_ingot","localizedName":"Copper Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.copper_ingot"},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_ore"},{"id":"minecraft:copper_trapdoor","localizedName":"Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_trapdoor"},{"id":"minecraft:cornflower","localizedName":"Cornflower","maxStackSize":64,"unlocalizedName":"block.minecraft.cornflower"},{"id":"minecraft:cow_spawn_egg","localizedName":"Cow Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cow_spawn_egg"},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_bricks"},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_tiles"},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_nether_bricks"},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_polished_blackstone_bricks"},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_stone_bricks"},{"id":"minecraft:crafter","localizedName":"Crafter","maxStackSize":64,"unlocalizedName":"block.minecraft.crafter"},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","maxStackSize":64,"unlocalizedName":"block.minecraft.crafting_table"},{"id":"minecraft:creeper_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.creeper_banner_pattern"},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","maxStackSize":64,"unlocalizedName":"block.minecraft.creeper_head"},{"id":"minecraft:creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.creeper_spawn_egg"},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_button"},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_door"},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence"},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence_gate"},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fungus"},{"id":"minecraft:crimson_hanging_sign","localizedName":"Crimson Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_hanging_sign"},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_hyphae"},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_nylium"},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_planks"},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_pressure_plate"},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_roots"},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_sign"},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_slab"},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stairs"},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stem"},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_trapdoor"},{"id":"minecraft:crossbow","localizedName":"Crossbow","maxDamage":465,"maxStackSize":1,"unlocalizedName":"item.minecraft.crossbow"},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","maxStackSize":64,"unlocalizedName":"block.minecraft.crying_obsidian"},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper"},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_slab"},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_stairs"},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone"},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone_slab"},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone"},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone_slab"},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.cyan_banner"},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_bed"},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_candle"},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_carpet"},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete"},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete_powder"},{"id":"minecraft:cyan_dye","localizedName":"Cyan Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.cyan_dye"},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_glazed_terracotta"},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_shulker_box"},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass"},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass_pane"},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_terracotta"},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_wool"},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.damaged_anvil"},{"id":"minecraft:dandelion","localizedName":"Dandelion","maxStackSize":64,"unlocalizedName":"block.minecraft.dandelion"},{"id":"minecraft:danger_pottery_sherd","localizedName":"Danger Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.danger_pottery_sherd"},{"id":"minecraft:dark_oak_boat","localizedName":"Dark Oak Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_boat"},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_button"},{"id":"minecraft:dark_oak_chest_boat","localizedName":"Dark Oak Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_chest_boat"},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_door"},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence"},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence_gate"},{"id":"minecraft:dark_oak_hanging_sign","localizedName":"Dark Oak Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_hanging_sign"},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_leaves"},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_log"},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_planks"},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_pressure_plate"},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_sapling"},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_sign"},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_slab"},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_stairs"},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_trapdoor"},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_wood"},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine"},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_slab"},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_stairs"},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","maxStackSize":64,"unlocalizedName":"block.minecraft.daylight_detector"},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral"},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_block"},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_fan"},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral"},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_block"},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_fan"},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bush"},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral"},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_block"},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_fan"},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral"},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_block"},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_fan"},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral"},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_block"},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_fan"},{"id":"minecraft:debug_stick","localizedName":"Debug Stick","maxStackSize":1,"unlocalizedName":"item.minecraft.debug_stick"},{"id":"minecraft:decorated_pot","localizedName":"Decorated Pot","maxStackSize":64,"unlocalizedName":"block.minecraft.decorated_pot"},{"id":"minecraft:deepslate","localizedName":"Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate"},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_slab"},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_stairs"},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_wall"},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_bricks"},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_coal_ore"},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_copper_ore"},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_diamond_ore"},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_emerald_ore"},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_gold_ore"},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_iron_ore"},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_lapis_ore"},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_redstone_ore"},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_slab"},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_stairs"},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_wall"},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tiles"},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.detector_rail"},{"id":"minecraft:diamond","localizedName":"Diamond","maxStackSize":64,"unlocalizedName":"item.minecraft.diamond"},{"id":"minecraft:diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_axe"},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_block"},{"id":"minecraft:diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_boots"},{"id":"minecraft:diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_chestplate"},{"id":"minecraft:diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_helmet"},{"id":"minecraft:diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_hoe"},{"id":"minecraft:diamond_horse_armor","localizedName":"Diamond Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_horse_armor"},{"id":"minecraft:diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_leggings"},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_ore"},{"id":"minecraft:diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_pickaxe"},{"id":"minecraft:diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_shovel"},{"id":"minecraft:diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_sword"},{"id":"minecraft:diorite","localizedName":"Diorite","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite"},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_slab"},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_stairs"},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_wall"},{"id":"minecraft:dirt","localizedName":"Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.dirt"},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","maxStackSize":64,"unlocalizedName":"block.minecraft.dirt_path"},{"id":"minecraft:disc_fragment_5","localizedName":"Disc Fragment","maxStackSize":64,"unlocalizedName":"item.minecraft.disc_fragment_5"},{"id":"minecraft:dispenser","localizedName":"Dispenser","maxStackSize":64,"unlocalizedName":"block.minecraft.dispenser"},{"id":"minecraft:dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.dolphin_spawn_egg"},{"id":"minecraft:donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.donkey_spawn_egg"},{"id":"minecraft:dragon_breath","localizedName":"Dragon\u0027s Breath","maxStackSize":64,"unlocalizedName":"item.minecraft.dragon_breath"},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_egg"},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_head"},{"id":"minecraft:dried_kelp","localizedName":"Dried Kelp","maxStackSize":64,"unlocalizedName":"item.minecraft.dried_kelp"},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dried_kelp_block"},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dripstone_block"},{"id":"minecraft:dropper","localizedName":"Dropper","maxStackSize":64,"unlocalizedName":"block.minecraft.dropper"},{"id":"minecraft:drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.drowned_spawn_egg"},{"id":"minecraft:dune_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.dune_armor_trim_smithing_template"},{"id":"minecraft:echo_shard","localizedName":"Echo Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.echo_shard"},{"id":"minecraft:egg","localizedName":"Egg","maxStackSize":16,"unlocalizedName":"item.minecraft.egg"},{"id":"minecraft:elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.elder_guardian_spawn_egg"},{"id":"minecraft:elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1,"unlocalizedName":"item.minecraft.elytra"},{"id":"minecraft:emerald","localizedName":"Emerald","maxStackSize":64,"unlocalizedName":"item.minecraft.emerald"},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_block"},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_ore"},{"id":"minecraft:enchanted_book","localizedName":"Enchanted Book","maxStackSize":1,"unlocalizedName":"item.minecraft.enchanted_book"},{"id":"minecraft:enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.enchanted_golden_apple"},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","maxStackSize":64,"unlocalizedName":"block.minecraft.enchanting_table"},{"id":"minecraft:end_crystal","localizedName":"End Crystal","maxStackSize":64,"unlocalizedName":"item.minecraft.end_crystal"},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","maxStackSize":64,"unlocalizedName":"block.minecraft.end_portal_frame"},{"id":"minecraft:end_rod","localizedName":"End Rod","maxStackSize":64,"unlocalizedName":"block.minecraft.end_rod"},{"id":"minecraft:end_stone","localizedName":"End Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone"},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_slab"},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_stairs"},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_wall"},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_bricks"},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.ender_chest"},{"id":"minecraft:ender_dragon_spawn_egg","localizedName":"Ender Dragon Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ender_dragon_spawn_egg"},{"id":"minecraft:ender_eye","localizedName":"Eye of Ender","maxStackSize":64,"unlocalizedName":"item.minecraft.ender_eye"},{"id":"minecraft:ender_pearl","localizedName":"Ender Pearl","maxStackSize":16,"unlocalizedName":"item.minecraft.ender_pearl"},{"id":"minecraft:enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.enderman_spawn_egg"},{"id":"minecraft:endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.endermite_spawn_egg"},{"id":"minecraft:evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.evoker_spawn_egg"},{"id":"minecraft:experience_bottle","localizedName":"Bottle o\u0027 Enchanting","maxStackSize":64,"unlocalizedName":"item.minecraft.experience_bottle"},{"id":"minecraft:explorer_pottery_sherd","localizedName":"Explorer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.explorer_pottery_sherd"},{"id":"minecraft:exposed_chiseled_copper","localizedName":"Exposed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_chiseled_copper"},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper"},{"id":"minecraft:exposed_copper_bulb","localizedName":"Exposed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_bulb"},{"id":"minecraft:exposed_copper_door","localizedName":"Exposed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_door"},{"id":"minecraft:exposed_copper_grate","localizedName":"Exposed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_grate"},{"id":"minecraft:exposed_copper_trapdoor","localizedName":"Exposed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_trapdoor"},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper"},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_slab"},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_stairs"},{"id":"minecraft:eye_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.eye_armor_trim_smithing_template"},{"id":"minecraft:farmland","localizedName":"Farmland","maxStackSize":64,"unlocalizedName":"block.minecraft.farmland"},{"id":"minecraft:feather","localizedName":"Feather","maxStackSize":64,"unlocalizedName":"item.minecraft.feather"},{"id":"minecraft:fermented_spider_eye","localizedName":"Fermented Spider Eye","maxStackSize":64,"unlocalizedName":"item.minecraft.fermented_spider_eye"},{"id":"minecraft:fern","localizedName":"Fern","maxStackSize":64,"unlocalizedName":"block.minecraft.fern"},{"id":"minecraft:filled_map","localizedName":"Map","maxStackSize":64,"unlocalizedName":"item.minecraft.filled_map"},{"id":"minecraft:fire_charge","localizedName":"Fire Charge","maxStackSize":64,"unlocalizedName":"item.minecraft.fire_charge"},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral"},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_block"},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_fan"},{"id":"minecraft:firework_rocket","localizedName":"Firework Rocket","maxStackSize":64,"unlocalizedName":"item.minecraft.firework_rocket"},{"id":"minecraft:firework_star","localizedName":"Firework Star","maxStackSize":64,"unlocalizedName":"item.minecraft.firework_star"},{"id":"minecraft:fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.fishing_rod"},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","maxStackSize":64,"unlocalizedName":"block.minecraft.fletching_table"},{"id":"minecraft:flint","localizedName":"Flint","maxStackSize":64,"unlocalizedName":"item.minecraft.flint"},{"id":"minecraft:flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.flint_and_steel"},{"id":"minecraft:flow_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.flow_armor_trim_smithing_template"},{"id":"minecraft:flow_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.flow_banner_pattern"},{"id":"minecraft:flow_pottery_sherd","localizedName":"Flow Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.flow_pottery_sherd"},{"id":"minecraft:flower_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.flower_banner_pattern"},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","maxStackSize":64,"unlocalizedName":"block.minecraft.flower_pot"},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea"},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea_leaves"},{"id":"minecraft:fox_spawn_egg","localizedName":"Fox Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.fox_spawn_egg"},{"id":"minecraft:friend_pottery_sherd","localizedName":"Friend Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.friend_pottery_sherd"},{"id":"minecraft:frog_spawn_egg","localizedName":"Frog Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.frog_spawn_egg"},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","maxStackSize":64,"unlocalizedName":"block.minecraft.frogspawn"},{"id":"minecraft:furnace","localizedName":"Furnace","maxStackSize":64,"unlocalizedName":"block.minecraft.furnace"},{"id":"minecraft:furnace_minecart","localizedName":"Minecart with Furnace","maxStackSize":1,"unlocalizedName":"item.minecraft.furnace_minecart"},{"id":"minecraft:ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_spawn_egg"},{"id":"minecraft:ghast_tear","localizedName":"Ghast Tear","maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_tear"},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.gilded_blackstone"},{"id":"minecraft:glass","localizedName":"Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.glass"},{"id":"minecraft:glass_bottle","localizedName":"Glass Bottle","maxStackSize":64,"unlocalizedName":"item.minecraft.glass_bottle"},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.glass_pane"},{"id":"minecraft:glistering_melon_slice","localizedName":"Glistering Melon Slice","maxStackSize":64,"unlocalizedName":"item.minecraft.glistering_melon_slice"},{"id":"minecraft:globe_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.globe_banner_pattern"},{"id":"minecraft:glow_berries","localizedName":"Glow Berries","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_berries"},{"id":"minecraft:glow_ink_sac","localizedName":"Glow Ink Sac","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_ink_sac"},{"id":"minecraft:glow_item_frame","localizedName":"Glow Item Frame","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_item_frame"},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","maxStackSize":64,"unlocalizedName":"block.minecraft.glow_lichen"},{"id":"minecraft:glow_squid_spawn_egg","localizedName":"Glow Squid Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_squid_spawn_egg"},{"id":"minecraft:glowstone","localizedName":"Glowstone","maxStackSize":64,"unlocalizedName":"block.minecraft.glowstone"},{"id":"minecraft:glowstone_dust","localizedName":"Glowstone Dust","maxStackSize":64,"unlocalizedName":"item.minecraft.glowstone_dust"},{"id":"minecraft:goat_horn","localizedName":"Goat Horn","maxStackSize":1,"unlocalizedName":"item.minecraft.goat_horn"},{"id":"minecraft:goat_spawn_egg","localizedName":"Goat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.goat_spawn_egg"},{"id":"minecraft:gold_block","localizedName":"Block of Gold","maxStackSize":64,"unlocalizedName":"block.minecraft.gold_block"},{"id":"minecraft:gold_ingot","localizedName":"Gold Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.gold_ingot"},{"id":"minecraft:gold_nugget","localizedName":"Gold Nugget","maxStackSize":64,"unlocalizedName":"item.minecraft.gold_nugget"},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.gold_ore"},{"id":"minecraft:golden_apple","localizedName":"Golden Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.golden_apple"},{"id":"minecraft:golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_axe"},{"id":"minecraft:golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_boots"},{"id":"minecraft:golden_carrot","localizedName":"Golden Carrot","maxStackSize":64,"unlocalizedName":"item.minecraft.golden_carrot"},{"id":"minecraft:golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_chestplate"},{"id":"minecraft:golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_helmet"},{"id":"minecraft:golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_hoe"},{"id":"minecraft:golden_horse_armor","localizedName":"Golden Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.golden_horse_armor"},{"id":"minecraft:golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_leggings"},{"id":"minecraft:golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_pickaxe"},{"id":"minecraft:golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_shovel"},{"id":"minecraft:golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_sword"},{"id":"minecraft:granite","localizedName":"Granite","maxStackSize":64,"unlocalizedName":"block.minecraft.granite"},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_slab"},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_stairs"},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_wall"},{"id":"minecraft:grass_block","localizedName":"Grass Block","maxStackSize":64,"unlocalizedName":"block.minecraft.grass_block"},{"id":"minecraft:gravel","localizedName":"Gravel","maxStackSize":64,"unlocalizedName":"block.minecraft.gravel"},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.gray_banner"},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.gray_bed"},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_candle"},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_carpet"},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete"},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete_powder"},{"id":"minecraft:gray_dye","localizedName":"Gray Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.gray_dye"},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_glazed_terracotta"},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.gray_shulker_box"},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass"},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass_pane"},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_terracotta"},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_wool"},{"id":"minecraft:green_banner","localizedName":"Green Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.green_banner"},{"id":"minecraft:green_bed","localizedName":"Green Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.green_bed"},{"id":"minecraft:green_candle","localizedName":"Green Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.green_candle"},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.green_carpet"},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete"},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete_powder"},{"id":"minecraft:green_dye","localizedName":"Green Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.green_dye"},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.green_glazed_terracotta"},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.green_shulker_box"},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass"},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass_pane"},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.green_terracotta"},{"id":"minecraft:green_wool","localizedName":"Green Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.green_wool"},{"id":"minecraft:grindstone","localizedName":"Grindstone","maxStackSize":64,"unlocalizedName":"block.minecraft.grindstone"},{"id":"minecraft:guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.guardian_spawn_egg"},{"id":"minecraft:gunpowder","localizedName":"Gunpowder","maxStackSize":64,"unlocalizedName":"item.minecraft.gunpowder"},{"id":"minecraft:guster_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.guster_banner_pattern"},{"id":"minecraft:guster_pottery_sherd","localizedName":"Guster Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.guster_pottery_sherd"},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.hanging_roots"},{"id":"minecraft:hay_block","localizedName":"Hay Bale","maxStackSize":64,"unlocalizedName":"block.minecraft.hay_block"},{"id":"minecraft:heart_of_the_sea","localizedName":"Heart of the Sea","maxStackSize":64,"unlocalizedName":"item.minecraft.heart_of_the_sea"},{"id":"minecraft:heart_pottery_sherd","localizedName":"Heart Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.heart_pottery_sherd"},{"id":"minecraft:heartbreak_pottery_sherd","localizedName":"Heartbreak Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.heartbreak_pottery_sherd"},{"id":"minecraft:heavy_core","localizedName":"Heavy Core","maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_core"},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate"},{"id":"minecraft:hoglin_spawn_egg","localizedName":"Hoglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.hoglin_spawn_egg"},{"id":"minecraft:honey_block","localizedName":"Honey Block","maxStackSize":64,"unlocalizedName":"block.minecraft.honey_block"},{"id":"minecraft:honey_bottle","localizedName":"Honey Bottle","maxStackSize":16,"unlocalizedName":"item.minecraft.honey_bottle"},{"id":"minecraft:honeycomb","localizedName":"Honeycomb","maxStackSize":64,"unlocalizedName":"item.minecraft.honeycomb"},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","maxStackSize":64,"unlocalizedName":"block.minecraft.honeycomb_block"},{"id":"minecraft:hopper","localizedName":"Hopper","maxStackSize":64,"unlocalizedName":"block.minecraft.hopper"},{"id":"minecraft:hopper_minecart","localizedName":"Minecart with Hopper","maxStackSize":1,"unlocalizedName":"item.minecraft.hopper_minecart"},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral"},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_block"},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_fan"},{"id":"minecraft:horse_spawn_egg","localizedName":"Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.horse_spawn_egg"},{"id":"minecraft:host_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.host_armor_trim_smithing_template"},{"id":"minecraft:howl_pottery_sherd","localizedName":"Howl Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.howl_pottery_sherd"},{"id":"minecraft:husk_spawn_egg","localizedName":"Husk Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.husk_spawn_egg"},{"id":"minecraft:ice","localizedName":"Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.ice"},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks"},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cobblestone"},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cracked_stone_bricks"},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_deepslate"},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_mossy_stone_bricks"},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone"},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone_bricks"},{"id":"minecraft:ink_sac","localizedName":"Ink Sac","maxStackSize":64,"unlocalizedName":"item.minecraft.ink_sac"},{"id":"minecraft:iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_axe"},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_bars"},{"id":"minecraft:iron_block","localizedName":"Block of Iron","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_block"},{"id":"minecraft:iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_boots"},{"id":"minecraft:iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_chestplate"},{"id":"minecraft:iron_door","localizedName":"Iron Door","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_door"},{"id":"minecraft:iron_golem_spawn_egg","localizedName":"Iron Golem Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_golem_spawn_egg"},{"id":"minecraft:iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_helmet"},{"id":"minecraft:iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_hoe"},{"id":"minecraft:iron_horse_armor","localizedName":"Iron Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.iron_horse_armor"},{"id":"minecraft:iron_ingot","localizedName":"Iron Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_ingot"},{"id":"minecraft:iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_leggings"},{"id":"minecraft:iron_nugget","localizedName":"Iron Nugget","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_nugget"},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_ore"},{"id":"minecraft:iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_pickaxe"},{"id":"minecraft:iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_shovel"},{"id":"minecraft:iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_sword"},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_trapdoor"},{"id":"minecraft:item_frame","localizedName":"Item Frame","maxStackSize":64,"unlocalizedName":"item.minecraft.item_frame"},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.jack_o_lantern"},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","maxStackSize":64,"unlocalizedName":"block.minecraft.jigsaw"},{"id":"minecraft:jukebox","localizedName":"Jukebox","maxStackSize":64,"unlocalizedName":"block.minecraft.jukebox"},{"id":"minecraft:jungle_boat","localizedName":"Jungle Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_boat"},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_button"},{"id":"minecraft:jungle_chest_boat","localizedName":"Jungle Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_chest_boat"},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_door"},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence"},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence_gate"},{"id":"minecraft:jungle_hanging_sign","localizedName":"Jungle Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_hanging_sign"},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_leaves"},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_log"},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_planks"},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_pressure_plate"},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_sapling"},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_sign"},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_slab"},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_stairs"},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_trapdoor"},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_wood"},{"id":"minecraft:kelp","localizedName":"Kelp","maxStackSize":64,"unlocalizedName":"block.minecraft.kelp"},{"id":"minecraft:knowledge_book","localizedName":"Knowledge Book","maxStackSize":1,"unlocalizedName":"item.minecraft.knowledge_book"},{"id":"minecraft:ladder","localizedName":"Ladder","maxStackSize":64,"unlocalizedName":"block.minecraft.ladder"},{"id":"minecraft:lantern","localizedName":"Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.lantern"},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_block"},{"id":"minecraft:lapis_lazuli","localizedName":"Lapis Lazuli","maxStackSize":64,"unlocalizedName":"item.minecraft.lapis_lazuli"},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_ore"},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.large_amethyst_bud"},{"id":"minecraft:large_fern","localizedName":"Large Fern","maxStackSize":64,"unlocalizedName":"block.minecraft.large_fern"},{"id":"minecraft:lava_bucket","localizedName":"Lava Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.lava_bucket"},{"id":"minecraft:lead","localizedName":"Lead","maxStackSize":64,"unlocalizedName":"item.minecraft.lead"},{"id":"minecraft:leather","localizedName":"Leather","maxStackSize":64,"unlocalizedName":"item.minecraft.leather"},{"id":"minecraft:leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_boots"},{"id":"minecraft:leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_chestplate"},{"id":"minecraft:leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_helmet"},{"id":"minecraft:leather_horse_armor","localizedName":"Leather Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.leather_horse_armor"},{"id":"minecraft:leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_leggings"},{"id":"minecraft:lectern","localizedName":"Lectern","maxStackSize":64,"unlocalizedName":"block.minecraft.lectern"},{"id":"minecraft:lever","localizedName":"Lever","maxStackSize":64,"unlocalizedName":"block.minecraft.lever"},{"id":"minecraft:light","localizedName":"Light","maxStackSize":64,"unlocalizedName":"block.minecraft.light"},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.light_blue_banner"},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_bed"},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_candle"},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_carpet"},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete"},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete_powder"},{"id":"minecraft:light_blue_dye","localizedName":"Light Blue Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.light_blue_dye"},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_glazed_terracotta"},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_shulker_box"},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass"},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass_pane"},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_terracotta"},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_wool"},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.light_gray_banner"},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_bed"},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_candle"},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_carpet"},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete"},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete_powder"},{"id":"minecraft:light_gray_dye","localizedName":"Light Gray Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.light_gray_dye"},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_glazed_terracotta"},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_shulker_box"},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass"},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass_pane"},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_terracotta"},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_wool"},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.light_weighted_pressure_plate"},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","maxStackSize":64,"unlocalizedName":"block.minecraft.lightning_rod"},{"id":"minecraft:lilac","localizedName":"Lilac","maxStackSize":64,"unlocalizedName":"block.minecraft.lilac"},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","maxStackSize":64,"unlocalizedName":"block.minecraft.lily_of_the_valley"},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","maxStackSize":64,"unlocalizedName":"block.minecraft.lily_pad"},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.lime_banner"},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.lime_bed"},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_candle"},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_carpet"},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete"},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete_powder"},{"id":"minecraft:lime_dye","localizedName":"Lime Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.lime_dye"},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_glazed_terracotta"},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.lime_shulker_box"},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass"},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass_pane"},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_terracotta"},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_wool"},{"id":"minecraft:lingering_potion","localizedName":"Lingering Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.lingering_potion.effect.water"},{"id":"minecraft:llama_spawn_egg","localizedName":"Llama Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.llama_spawn_egg"},{"id":"minecraft:lodestone","localizedName":"Lodestone","maxStackSize":64,"unlocalizedName":"block.minecraft.lodestone"},{"id":"minecraft:loom","localizedName":"Loom","maxStackSize":64,"unlocalizedName":"block.minecraft.loom"},{"id":"minecraft:mace","localizedName":"Mace","maxDamage":500,"maxStackSize":1,"unlocalizedName":"item.minecraft.mace"},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.magenta_banner"},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_bed"},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_candle"},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_carpet"},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete"},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete_powder"},{"id":"minecraft:magenta_dye","localizedName":"Magenta Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.magenta_dye"},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_glazed_terracotta"},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_shulker_box"},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass"},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass_pane"},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_terracotta"},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_wool"},{"id":"minecraft:magma_block","localizedName":"Magma Block","maxStackSize":64,"unlocalizedName":"block.minecraft.magma_block"},{"id":"minecraft:magma_cream","localizedName":"Magma Cream","maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cream"},{"id":"minecraft:magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cube_spawn_egg"},{"id":"minecraft:mangrove_boat","localizedName":"Mangrove Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_boat"},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_button"},{"id":"minecraft:mangrove_chest_boat","localizedName":"Mangrove Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_chest_boat"},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_door"},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence"},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence_gate"},{"id":"minecraft:mangrove_hanging_sign","localizedName":"Mangrove Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.mangrove_hanging_sign"},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_leaves"},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_log"},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_planks"},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_pressure_plate"},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_propagule"},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_roots"},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.mangrove_sign"},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_slab"},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_stairs"},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_trapdoor"},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_wood"},{"id":"minecraft:map","localizedName":"Empty Map","maxStackSize":64,"unlocalizedName":"item.minecraft.map"},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.medium_amethyst_bud"},{"id":"minecraft:melon","localizedName":"Melon","maxStackSize":64,"unlocalizedName":"block.minecraft.melon"},{"id":"minecraft:melon_seeds","localizedName":"Melon Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.melon_seeds"},{"id":"minecraft:melon_slice","localizedName":"Melon Slice","maxStackSize":64,"unlocalizedName":"item.minecraft.melon_slice"},{"id":"minecraft:milk_bucket","localizedName":"Milk Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.milk_bucket"},{"id":"minecraft:minecart","localizedName":"Minecart","maxStackSize":1,"unlocalizedName":"item.minecraft.minecart"},{"id":"minecraft:miner_pottery_sherd","localizedName":"Miner Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.miner_pottery_sherd"},{"id":"minecraft:mojang_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.mojang_banner_pattern"},{"id":"minecraft:mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.mooshroom_spawn_egg"},{"id":"minecraft:moss_block","localizedName":"Moss Block","maxStackSize":64,"unlocalizedName":"block.minecraft.moss_block"},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.moss_carpet"},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone"},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_slab"},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_stairs"},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_wall"},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_slab"},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_stairs"},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_wall"},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_bricks"},{"id":"minecraft:mourner_pottery_sherd","localizedName":"Mourner Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.mourner_pottery_sherd"},{"id":"minecraft:mud","localizedName":"Mud","maxStackSize":64,"unlocalizedName":"block.minecraft.mud"},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_slab"},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_stairs"},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_wall"},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_bricks"},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.muddy_mangrove_roots"},{"id":"minecraft:mule_spawn_egg","localizedName":"Mule Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.mule_spawn_egg"},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.mushroom_stem"},{"id":"minecraft:mushroom_stew","localizedName":"Mushroom Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.mushroom_stew"},{"id":"minecraft:music_disc_11","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_11"},{"id":"minecraft:music_disc_13","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_13"},{"id":"minecraft:music_disc_5","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_5"},{"id":"minecraft:music_disc_blocks","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_blocks"},{"id":"minecraft:music_disc_cat","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_cat"},{"id":"minecraft:music_disc_chirp","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_chirp"},{"id":"minecraft:music_disc_creator","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_creator"},{"id":"minecraft:music_disc_creator_music_box","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_creator_music_box"},{"id":"minecraft:music_disc_far","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_far"},{"id":"minecraft:music_disc_mall","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mall"},{"id":"minecraft:music_disc_mellohi","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mellohi"},{"id":"minecraft:music_disc_otherside","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_otherside"},{"id":"minecraft:music_disc_pigstep","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_pigstep"},{"id":"minecraft:music_disc_precipice","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_precipice"},{"id":"minecraft:music_disc_relic","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_relic"},{"id":"minecraft:music_disc_stal","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_stal"},{"id":"minecraft:music_disc_strad","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_strad"},{"id":"minecraft:music_disc_wait","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_wait"},{"id":"minecraft:music_disc_ward","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_ward"},{"id":"minecraft:mutton","localizedName":"Raw Mutton","maxStackSize":64,"unlocalizedName":"item.minecraft.mutton"},{"id":"minecraft:mycelium","localizedName":"Mycelium","maxStackSize":64,"unlocalizedName":"block.minecraft.mycelium"},{"id":"minecraft:name_tag","localizedName":"Name Tag","maxStackSize":64,"unlocalizedName":"item.minecraft.name_tag"},{"id":"minecraft:nautilus_shell","localizedName":"Nautilus Shell","maxStackSize":64,"unlocalizedName":"item.minecraft.nautilus_shell"},{"id":"minecraft:nether_brick","localizedName":"Nether Brick","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_brick"},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_fence"},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_slab"},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_stairs"},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_wall"},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_bricks"},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_gold_ore"},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_quartz_ore"},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_sprouts"},{"id":"minecraft:nether_star","localizedName":"Nether Star","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_star"},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_wart"},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_wart_block"},{"id":"minecraft:netherite_axe","localizedName":"Netherite Axe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_axe"},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","maxStackSize":64,"unlocalizedName":"block.minecraft.netherite_block"},{"id":"minecraft:netherite_boots","localizedName":"Netherite Boots","maxDamage":481,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_boots"},{"id":"minecraft:netherite_chestplate","localizedName":"Netherite Chestplate","maxDamage":592,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_chestplate"},{"id":"minecraft:netherite_helmet","localizedName":"Netherite Helmet","maxDamage":407,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_helmet"},{"id":"minecraft:netherite_hoe","localizedName":"Netherite Hoe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_hoe"},{"id":"minecraft:netherite_ingot","localizedName":"Netherite Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_ingot"},{"id":"minecraft:netherite_leggings","localizedName":"Netherite Leggings","maxDamage":555,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_leggings"},{"id":"minecraft:netherite_pickaxe","localizedName":"Netherite Pickaxe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_pickaxe"},{"id":"minecraft:netherite_scrap","localizedName":"Netherite Scrap","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_scrap"},{"id":"minecraft:netherite_shovel","localizedName":"Netherite Shovel","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_shovel"},{"id":"minecraft:netherite_sword","localizedName":"Netherite Sword","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_sword"},{"id":"minecraft:netherite_upgrade_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_upgrade_smithing_template"},{"id":"minecraft:netherrack","localizedName":"Netherrack","maxStackSize":64,"unlocalizedName":"block.minecraft.netherrack"},{"id":"minecraft:note_block","localizedName":"Note Block","maxStackSize":64,"unlocalizedName":"block.minecraft.note_block"},{"id":"minecraft:oak_boat","localizedName":"Oak Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.oak_boat"},{"id":"minecraft:oak_button","localizedName":"Oak Button","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_button"},{"id":"minecraft:oak_chest_boat","localizedName":"Oak Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.oak_chest_boat"},{"id":"minecraft:oak_door","localizedName":"Oak Door","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_door"},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence"},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence_gate"},{"id":"minecraft:oak_hanging_sign","localizedName":"Oak Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.oak_hanging_sign"},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_leaves"},{"id":"minecraft:oak_log","localizedName":"Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_log"},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_planks"},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_pressure_plate"},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_sapling"},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.oak_sign"},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_slab"},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_stairs"},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_trapdoor"},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_wood"},{"id":"minecraft:observer","localizedName":"Observer","maxStackSize":64,"unlocalizedName":"block.minecraft.observer"},{"id":"minecraft:obsidian","localizedName":"Obsidian","maxStackSize":64,"unlocalizedName":"block.minecraft.obsidian"},{"id":"minecraft:ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ocelot_spawn_egg"},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.ochre_froglight"},{"id":"minecraft:ominous_bottle","localizedName":"Ominous Bottle","maxStackSize":64,"unlocalizedName":"item.minecraft.ominous_bottle"},{"id":"minecraft:ominous_trial_key","localizedName":"Ominous Trial Key","maxStackSize":64,"unlocalizedName":"item.minecraft.ominous_trial_key"},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.orange_banner"},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.orange_bed"},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_candle"},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_carpet"},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete"},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete_powder"},{"id":"minecraft:orange_dye","localizedName":"Orange Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.orange_dye"},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_glazed_terracotta"},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.orange_shulker_box"},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass"},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass_pane"},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_terracotta"},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_tulip"},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_wool"},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","maxStackSize":64,"unlocalizedName":"block.minecraft.oxeye_daisy"},{"id":"minecraft:oxidized_chiseled_copper","localizedName":"Oxidized Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_chiseled_copper"},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper"},{"id":"minecraft:oxidized_copper_bulb","localizedName":"Oxidized Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_bulb"},{"id":"minecraft:oxidized_copper_door","localizedName":"Oxidized Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_door"},{"id":"minecraft:oxidized_copper_grate","localizedName":"Oxidized Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_grate"},{"id":"minecraft:oxidized_copper_trapdoor","localizedName":"Oxidized Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_trapdoor"},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper"},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_slab"},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_stairs"},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.packed_ice"},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","maxStackSize":64,"unlocalizedName":"block.minecraft.packed_mud"},{"id":"minecraft:painting","localizedName":"Painting","maxStackSize":64,"unlocalizedName":"item.minecraft.painting"},{"id":"minecraft:panda_spawn_egg","localizedName":"Panda Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.panda_spawn_egg"},{"id":"minecraft:paper","localizedName":"Paper","maxStackSize":64,"unlocalizedName":"item.minecraft.paper"},{"id":"minecraft:parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.parrot_spawn_egg"},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.pearlescent_froglight"},{"id":"minecraft:peony","localizedName":"Peony","maxStackSize":64,"unlocalizedName":"block.minecraft.peony"},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.petrified_oak_slab"},{"id":"minecraft:phantom_membrane","localizedName":"Phantom Membrane","maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_membrane"},{"id":"minecraft:phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_spawn_egg"},{"id":"minecraft:pig_spawn_egg","localizedName":"Pig Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pig_spawn_egg"},{"id":"minecraft:piglin_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.piglin_banner_pattern"},{"id":"minecraft:piglin_brute_spawn_egg","localizedName":"Piglin Brute Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_brute_spawn_egg"},{"id":"minecraft:piglin_head","localizedName":"Piglin Head","maxStackSize":64,"unlocalizedName":"block.minecraft.piglin_head"},{"id":"minecraft:piglin_spawn_egg","localizedName":"Piglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_spawn_egg"},{"id":"minecraft:pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pillager_spawn_egg"},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.pink_banner"},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.pink_bed"},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_candle"},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_carpet"},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete"},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete_powder"},{"id":"minecraft:pink_dye","localizedName":"Pink Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.pink_dye"},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_glazed_terracotta"},{"id":"minecraft:pink_petals","localizedName":"Pink Petals","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_petals"},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.pink_shulker_box"},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass"},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass_pane"},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_terracotta"},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_tulip"},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_wool"},{"id":"minecraft:piston","localizedName":"Piston","maxStackSize":64,"unlocalizedName":"block.minecraft.piston"},{"id":"minecraft:pitcher_plant","localizedName":"Pitcher Plant","maxStackSize":64,"unlocalizedName":"block.minecraft.pitcher_plant"},{"id":"minecraft:pitcher_pod","localizedName":"Pitcher Pod","maxStackSize":64,"unlocalizedName":"item.minecraft.pitcher_pod"},{"id":"minecraft:player_head","localizedName":"Player Head","maxStackSize":64,"unlocalizedName":"block.minecraft.player_head"},{"id":"minecraft:plenty_pottery_sherd","localizedName":"Plenty Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.plenty_pottery_sherd"},{"id":"minecraft:podzol","localizedName":"Podzol","maxStackSize":64,"unlocalizedName":"block.minecraft.podzol"},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","maxStackSize":64,"unlocalizedName":"block.minecraft.pointed_dripstone"},{"id":"minecraft:poisonous_potato","localizedName":"Poisonous Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.poisonous_potato"},{"id":"minecraft:polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.polar_bear_spawn_egg"},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite"},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_slab"},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_stairs"},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_basalt"},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone"},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_slab"},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_stairs"},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_wall"},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_bricks"},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_button"},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_pressure_plate"},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_slab"},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_stairs"},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_wall"},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate"},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_slab"},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_stairs"},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_wall"},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite"},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_slab"},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_stairs"},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite"},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_slab"},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_stairs"},{"id":"minecraft:polished_tuff","localizedName":"Polished Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff"},{"id":"minecraft:polished_tuff_slab","localizedName":"Polished Tuff Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_slab"},{"id":"minecraft:polished_tuff_stairs","localizedName":"Polished Tuff Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_stairs"},{"id":"minecraft:polished_tuff_wall","localizedName":"Polished Tuff Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_wall"},{"id":"minecraft:popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxStackSize":64,"unlocalizedName":"item.minecraft.popped_chorus_fruit"},{"id":"minecraft:poppy","localizedName":"Poppy","maxStackSize":64,"unlocalizedName":"block.minecraft.poppy"},{"id":"minecraft:porkchop","localizedName":"Raw Porkchop","maxStackSize":64,"unlocalizedName":"item.minecraft.porkchop"},{"id":"minecraft:potato","localizedName":"Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.potato"},{"id":"minecraft:potion","localizedName":"Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.potion.effect.water"},{"id":"minecraft:powder_snow_bucket","localizedName":"Powder Snow Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.powder_snow_bucket"},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.powered_rail"},{"id":"minecraft:prismarine","localizedName":"Prismarine","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine"},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_slab"},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_stairs"},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_bricks"},{"id":"minecraft:prismarine_crystals","localizedName":"Prismarine Crystals","maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_crystals"},{"id":"minecraft:prismarine_shard","localizedName":"Prismarine Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_shard"},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_slab"},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_stairs"},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_wall"},{"id":"minecraft:prize_pottery_sherd","localizedName":"Prize Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.prize_pottery_sherd"},{"id":"minecraft:pufferfish","localizedName":"Pufferfish","maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish"},{"id":"minecraft:pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxStackSize":1,"unlocalizedName":"item.minecraft.pufferfish_bucket"},{"id":"minecraft:pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish_spawn_egg"},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","maxStackSize":64,"unlocalizedName":"block.minecraft.pumpkin"},{"id":"minecraft:pumpkin_pie","localizedName":"Pumpkin Pie","maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_pie"},{"id":"minecraft:pumpkin_seeds","localizedName":"Pumpkin Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_seeds"},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.purple_banner"},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.purple_bed"},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_candle"},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_carpet"},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete"},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete_powder"},{"id":"minecraft:purple_dye","localizedName":"Purple Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.purple_dye"},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_glazed_terracotta"},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.purple_shulker_box"},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass"},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass_pane"},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_terracotta"},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_wool"},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_block"},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_pillar"},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_slab"},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_stairs"},{"id":"minecraft:quartz","localizedName":"Nether Quartz","maxStackSize":64,"unlocalizedName":"item.minecraft.quartz"},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_block"},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_bricks"},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_pillar"},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_slab"},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_stairs"},{"id":"minecraft:rabbit","localizedName":"Raw Rabbit","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit"},{"id":"minecraft:rabbit_foot","localizedName":"Rabbit\u0027s Foot","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_foot"},{"id":"minecraft:rabbit_hide","localizedName":"Rabbit Hide","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_hide"},{"id":"minecraft:rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_spawn_egg"},{"id":"minecraft:rabbit_stew","localizedName":"Rabbit Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.rabbit_stew"},{"id":"minecraft:rail","localizedName":"Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.rail"},{"id":"minecraft:raiser_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.raiser_armor_trim_smithing_template"},{"id":"minecraft:ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ravager_spawn_egg"},{"id":"minecraft:raw_copper","localizedName":"Raw Copper","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_copper"},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_copper_block"},{"id":"minecraft:raw_gold","localizedName":"Raw Gold","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_gold"},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_gold_block"},{"id":"minecraft:raw_iron","localizedName":"Raw Iron","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_iron"},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_iron_block"},{"id":"minecraft:recovery_compass","localizedName":"Recovery Compass","maxStackSize":64,"unlocalizedName":"item.minecraft.recovery_compass"},{"id":"minecraft:red_banner","localizedName":"Red Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.red_banner"},{"id":"minecraft:red_bed","localizedName":"Red Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.red_bed"},{"id":"minecraft:red_candle","localizedName":"Red Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.red_candle"},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.red_carpet"},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete"},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete_powder"},{"id":"minecraft:red_dye","localizedName":"Red Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.red_dye"},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.red_glazed_terracotta"},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom"},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom_block"},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_slab"},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_stairs"},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_wall"},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_bricks"},{"id":"minecraft:red_sand","localizedName":"Red Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sand"},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone"},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_slab"},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_stairs"},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_wall"},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.red_shulker_box"},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass"},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass_pane"},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.red_terracotta"},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.red_tulip"},{"id":"minecraft:red_wool","localizedName":"Red Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.red_wool"},{"id":"minecraft:redstone","localizedName":"Redstone Dust","maxStackSize":64,"unlocalizedName":"item.minecraft.redstone"},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_block"},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_lamp"},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_ore"},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_torch"},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.reinforced_deepslate"},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","maxStackSize":64,"unlocalizedName":"block.minecraft.repeater"},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.repeating_command_block"},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","maxStackSize":64,"unlocalizedName":"block.minecraft.respawn_anchor"},{"id":"minecraft:rib_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.rib_armor_trim_smithing_template"},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.rooted_dirt"},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","maxStackSize":64,"unlocalizedName":"block.minecraft.rose_bush"},{"id":"minecraft:rotten_flesh","localizedName":"Rotten Flesh","maxStackSize":64,"unlocalizedName":"item.minecraft.rotten_flesh"},{"id":"minecraft:saddle","localizedName":"Saddle","maxStackSize":1,"unlocalizedName":"item.minecraft.saddle"},{"id":"minecraft:salmon","localizedName":"Raw Salmon","maxStackSize":64,"unlocalizedName":"item.minecraft.salmon"},{"id":"minecraft:salmon_bucket","localizedName":"Bucket of Salmon","maxStackSize":1,"unlocalizedName":"item.minecraft.salmon_bucket"},{"id":"minecraft:salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.salmon_spawn_egg"},{"id":"minecraft:sand","localizedName":"Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.sand"},{"id":"minecraft:sandstone","localizedName":"Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone"},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_slab"},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_stairs"},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_wall"},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","maxStackSize":64,"unlocalizedName":"block.minecraft.scaffolding"},{"id":"minecraft:scrape_pottery_sherd","localizedName":"Scrape Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.scrape_pottery_sherd"},{"id":"minecraft:sculk","localizedName":"Sculk","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk"},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_catalyst"},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_sensor"},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_shrieker"},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_vein"},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.sea_lantern"},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","maxStackSize":64,"unlocalizedName":"block.minecraft.sea_pickle"},{"id":"minecraft:seagrass","localizedName":"Seagrass","maxStackSize":64,"unlocalizedName":"block.minecraft.seagrass"},{"id":"minecraft:sentry_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.sentry_armor_trim_smithing_template"},{"id":"minecraft:shaper_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.shaper_armor_trim_smithing_template"},{"id":"minecraft:sheaf_pottery_sherd","localizedName":"Sheaf Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.sheaf_pottery_sherd"},{"id":"minecraft:shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1,"unlocalizedName":"item.minecraft.shears"},{"id":"minecraft:sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.sheep_spawn_egg"},{"id":"minecraft:shelter_pottery_sherd","localizedName":"Shelter Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.shelter_pottery_sherd"},{"id":"minecraft:shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1,"unlocalizedName":"item.minecraft.shield"},{"id":"minecraft:short_grass","localizedName":"Short Grass","maxStackSize":64,"unlocalizedName":"block.minecraft.short_grass"},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","maxStackSize":64,"unlocalizedName":"block.minecraft.shroomlight"},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.shulker_box"},{"id":"minecraft:shulker_shell","localizedName":"Shulker Shell","maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_shell"},{"id":"minecraft:shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_spawn_egg"},{"id":"minecraft:silence_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.silence_armor_trim_smithing_template"},{"id":"minecraft:silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.silverfish_spawn_egg"},{"id":"minecraft:skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg"},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","maxStackSize":64,"unlocalizedName":"block.minecraft.skeleton_skull"},{"id":"minecraft:skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_spawn_egg"},{"id":"minecraft:skull_banner_pattern","localizedName":"Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.skull_banner_pattern"},{"id":"minecraft:skull_pottery_sherd","localizedName":"Skull Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.skull_pottery_sherd"},{"id":"minecraft:slime_ball","localizedName":"Slimeball","maxStackSize":64,"unlocalizedName":"item.minecraft.slime_ball"},{"id":"minecraft:slime_block","localizedName":"Slime Block","maxStackSize":64,"unlocalizedName":"block.minecraft.slime_block"},{"id":"minecraft:slime_spawn_egg","localizedName":"Slime Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.slime_spawn_egg"},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.small_amethyst_bud"},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","maxStackSize":64,"unlocalizedName":"block.minecraft.small_dripleaf"},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","maxStackSize":64,"unlocalizedName":"block.minecraft.smithing_table"},{"id":"minecraft:smoker","localizedName":"Smoker","maxStackSize":64,"unlocalizedName":"block.minecraft.smoker"},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_basalt"},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz"},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_slab"},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_stairs"},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone"},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_slab"},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs"},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone"},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_slab"},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_stairs"},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone"},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone_slab"},{"id":"minecraft:sniffer_egg","localizedName":"Sniffer Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.sniffer_egg"},{"id":"minecraft:sniffer_spawn_egg","localizedName":"Sniffer Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.sniffer_spawn_egg"},{"id":"minecraft:snort_pottery_sherd","localizedName":"Snort Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.snort_pottery_sherd"},{"id":"minecraft:snout_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.snout_armor_trim_smithing_template"},{"id":"minecraft:snow","localizedName":"Snow","maxStackSize":64,"unlocalizedName":"block.minecraft.snow"},{"id":"minecraft:snow_block","localizedName":"Snow Block","maxStackSize":64,"unlocalizedName":"block.minecraft.snow_block"},{"id":"minecraft:snow_golem_spawn_egg","localizedName":"Snow Golem Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.snow_golem_spawn_egg"},{"id":"minecraft:snowball","localizedName":"Snowball","maxStackSize":16,"unlocalizedName":"item.minecraft.snowball"},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_campfire"},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_lantern"},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_sand"},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_soil"},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_torch"},{"id":"minecraft:spawner","localizedName":"Monster Spawner","maxStackSize":64,"unlocalizedName":"block.minecraft.spawner"},{"id":"minecraft:spectral_arrow","localizedName":"Spectral Arrow","maxStackSize":64,"unlocalizedName":"item.minecraft.spectral_arrow"},{"id":"minecraft:spider_eye","localizedName":"Spider Eye","maxStackSize":64,"unlocalizedName":"item.minecraft.spider_eye"},{"id":"minecraft:spider_spawn_egg","localizedName":"Spider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.spider_spawn_egg"},{"id":"minecraft:spire_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.spire_armor_trim_smithing_template"},{"id":"minecraft:splash_potion","localizedName":"Splash Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.splash_potion.effect.water"},{"id":"minecraft:sponge","localizedName":"Sponge","maxStackSize":64,"unlocalizedName":"block.minecraft.sponge"},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","maxStackSize":64,"unlocalizedName":"block.minecraft.spore_blossom"},{"id":"minecraft:spruce_boat","localizedName":"Spruce Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_boat"},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_button"},{"id":"minecraft:spruce_chest_boat","localizedName":"Spruce Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_chest_boat"},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_door"},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence"},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence_gate"},{"id":"minecraft:spruce_hanging_sign","localizedName":"Spruce Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_hanging_sign"},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_leaves"},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_log"},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_planks"},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_pressure_plate"},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_sapling"},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_sign"},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_slab"},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_stairs"},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_trapdoor"},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_wood"},{"id":"minecraft:spyglass","localizedName":"Spyglass","maxStackSize":1,"unlocalizedName":"item.minecraft.spyglass"},{"id":"minecraft:squid_spawn_egg","localizedName":"Squid Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.squid_spawn_egg"},{"id":"minecraft:stick","localizedName":"Stick","maxStackSize":64,"unlocalizedName":"item.minecraft.stick"},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","maxStackSize":64,"unlocalizedName":"block.minecraft.sticky_piston"},{"id":"minecraft:stone","localizedName":"Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.stone"},{"id":"minecraft:stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_axe"},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_slab"},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_stairs"},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_wall"},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_bricks"},{"id":"minecraft:stone_button","localizedName":"Stone Button","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_button"},{"id":"minecraft:stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_hoe"},{"id":"minecraft:stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_pickaxe"},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_pressure_plate"},{"id":"minecraft:stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_shovel"},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_slab"},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_stairs"},{"id":"minecraft:stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_sword"},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","maxStackSize":64,"unlocalizedName":"block.minecraft.stonecutter"},{"id":"minecraft:stray_spawn_egg","localizedName":"Stray Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.stray_spawn_egg"},{"id":"minecraft:strider_spawn_egg","localizedName":"Strider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.strider_spawn_egg"},{"id":"minecraft:string","localizedName":"String","maxStackSize":64,"unlocalizedName":"item.minecraft.string"},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_log"},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_wood"},{"id":"minecraft:stripped_bamboo_block","localizedName":"Block of Stripped Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_bamboo_block"},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_log"},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_wood"},{"id":"minecraft:stripped_cherry_log","localizedName":"Stripped Cherry Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_cherry_log"},{"id":"minecraft:stripped_cherry_wood","localizedName":"Stripped Cherry Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_cherry_wood"},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_hyphae"},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_stem"},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_log"},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_wood"},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_log"},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_wood"},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_log"},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_wood"},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_log"},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_wood"},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_log"},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_wood"},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_hyphae"},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_stem"},{"id":"minecraft:structure_block","localizedName":"Structure Block","maxStackSize":64,"unlocalizedName":"block.minecraft.structure_block"},{"id":"minecraft:structure_void","localizedName":"Structure Void","maxStackSize":64,"unlocalizedName":"block.minecraft.structure_void"},{"id":"minecraft:sugar","localizedName":"Sugar","maxStackSize":64,"unlocalizedName":"item.minecraft.sugar"},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","maxStackSize":64,"unlocalizedName":"block.minecraft.sugar_cane"},{"id":"minecraft:sunflower","localizedName":"Sunflower","maxStackSize":64,"unlocalizedName":"block.minecraft.sunflower"},{"id":"minecraft:suspicious_gravel","localizedName":"Suspicious Gravel","maxStackSize":64,"unlocalizedName":"block.minecraft.suspicious_gravel"},{"id":"minecraft:suspicious_sand","localizedName":"Suspicious Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.suspicious_sand"},{"id":"minecraft:suspicious_stew","localizedName":"Suspicious Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.suspicious_stew"},{"id":"minecraft:sweet_berries","localizedName":"Sweet Berries","maxStackSize":64,"unlocalizedName":"item.minecraft.sweet_berries"},{"id":"minecraft:tadpole_bucket","localizedName":"Bucket of Tadpole","maxStackSize":1,"unlocalizedName":"item.minecraft.tadpole_bucket"},{"id":"minecraft:tadpole_spawn_egg","localizedName":"Tadpole Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.tadpole_spawn_egg"},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","maxStackSize":64,"unlocalizedName":"block.minecraft.tall_grass"},{"id":"minecraft:target","localizedName":"Target","maxStackSize":64,"unlocalizedName":"block.minecraft.target"},{"id":"minecraft:terracotta","localizedName":"Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.terracotta"},{"id":"minecraft:tide_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.tide_armor_trim_smithing_template"},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.tinted_glass"},{"id":"minecraft:tipped_arrow","localizedName":"Arrow of Poison","maxStackSize":64,"unlocalizedName":"item.minecraft.tipped_arrow.effect.poison"},{"id":"minecraft:tnt","localizedName":"TNT","maxStackSize":64,"unlocalizedName":"block.minecraft.tnt"},{"id":"minecraft:tnt_minecart","localizedName":"Minecart with TNT","maxStackSize":1,"unlocalizedName":"item.minecraft.tnt_minecart"},{"id":"minecraft:torch","localizedName":"Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.torch"},{"id":"minecraft:torchflower","localizedName":"Torchflower","maxStackSize":64,"unlocalizedName":"block.minecraft.torchflower"},{"id":"minecraft:torchflower_seeds","localizedName":"Torchflower Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.torchflower_seeds"},{"id":"minecraft:totem_of_undying","localizedName":"Totem of Undying","maxStackSize":1,"unlocalizedName":"item.minecraft.totem_of_undying"},{"id":"minecraft:trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.trader_llama_spawn_egg"},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.trapped_chest"},{"id":"minecraft:trial_key","localizedName":"Trial Key","maxStackSize":64,"unlocalizedName":"item.minecraft.trial_key"},{"id":"minecraft:trial_spawner","localizedName":"Trial Spawner","maxStackSize":64,"unlocalizedName":"block.minecraft.trial_spawner"},{"id":"minecraft:trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.trident"},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","maxStackSize":64,"unlocalizedName":"block.minecraft.tripwire_hook"},{"id":"minecraft:tropical_fish","localizedName":"Tropical Fish","maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish"},{"id":"minecraft:tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxStackSize":1,"unlocalizedName":"item.minecraft.tropical_fish_bucket"},{"id":"minecraft:tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish_spawn_egg"},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral"},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_block"},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_fan"},{"id":"minecraft:tuff","localizedName":"Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff"},{"id":"minecraft:tuff_brick_slab","localizedName":"Tuff Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_slab"},{"id":"minecraft:tuff_brick_stairs","localizedName":"Tuff Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_stairs"},{"id":"minecraft:tuff_brick_wall","localizedName":"Tuff Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_wall"},{"id":"minecraft:tuff_bricks","localizedName":"Tuff Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_bricks"},{"id":"minecraft:tuff_slab","localizedName":"Tuff Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_slab"},{"id":"minecraft:tuff_stairs","localizedName":"Tuff Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_stairs"},{"id":"minecraft:tuff_wall","localizedName":"Tuff Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_wall"},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.turtle_egg"},{"id":"minecraft:turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1,"unlocalizedName":"item.minecraft.turtle_helmet"},{"id":"minecraft:turtle_scute","localizedName":"Turtle Scute","maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_scute"},{"id":"minecraft:turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_spawn_egg"},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.twisting_vines"},{"id":"minecraft:vault","localizedName":"Vault","maxStackSize":64,"unlocalizedName":"block.minecraft.vault"},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.verdant_froglight"},{"id":"minecraft:vex_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.vex_armor_trim_smithing_template"},{"id":"minecraft:vex_spawn_egg","localizedName":"Vex Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.vex_spawn_egg"},{"id":"minecraft:villager_spawn_egg","localizedName":"Villager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.villager_spawn_egg"},{"id":"minecraft:vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.vindicator_spawn_egg"},{"id":"minecraft:vine","localizedName":"Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.vine"},{"id":"minecraft:wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wandering_trader_spawn_egg"},{"id":"minecraft:ward_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.ward_armor_trim_smithing_template"},{"id":"minecraft:warden_spawn_egg","localizedName":"Warden Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.warden_spawn_egg"},{"id":"minecraft:warped_button","localizedName":"Warped Button","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_button"},{"id":"minecraft:warped_door","localizedName":"Warped Door","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_door"},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence"},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence_gate"},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fungus"},{"id":"minecraft:warped_fungus_on_a_stick","localizedName":"Warped Fungus on a Stick","maxDamage":100,"maxStackSize":1,"unlocalizedName":"item.minecraft.warped_fungus_on_a_stick"},{"id":"minecraft:warped_hanging_sign","localizedName":"Warped Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.warped_hanging_sign"},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_hyphae"},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_nylium"},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_planks"},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_pressure_plate"},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_roots"},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.warped_sign"},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_slab"},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stairs"},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stem"},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_trapdoor"},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_wart_block"},{"id":"minecraft:water_bucket","localizedName":"Water Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.water_bucket"},{"id":"minecraft:waxed_chiseled_copper","localizedName":"Waxed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_chiseled_copper"},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_block"},{"id":"minecraft:waxed_copper_bulb","localizedName":"Waxed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_bulb"},{"id":"minecraft:waxed_copper_door","localizedName":"Waxed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_door"},{"id":"minecraft:waxed_copper_grate","localizedName":"Waxed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_grate"},{"id":"minecraft:waxed_copper_trapdoor","localizedName":"Waxed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_trapdoor"},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper"},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_slab"},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_stairs"},{"id":"minecraft:waxed_exposed_chiseled_copper","localizedName":"Waxed Exposed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_chiseled_copper"},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper"},{"id":"minecraft:waxed_exposed_copper_bulb","localizedName":"Waxed Exposed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_bulb"},{"id":"minecraft:waxed_exposed_copper_door","localizedName":"Waxed Exposed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_door"},{"id":"minecraft:waxed_exposed_copper_grate","localizedName":"Waxed Exposed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_grate"},{"id":"minecraft:waxed_exposed_copper_trapdoor","localizedName":"Waxed Exposed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_trapdoor"},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper"},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_slab"},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_stairs"},{"id":"minecraft:waxed_oxidized_chiseled_copper","localizedName":"Waxed Oxidized Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_chiseled_copper"},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper"},{"id":"minecraft:waxed_oxidized_copper_bulb","localizedName":"Waxed Oxidized Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_bulb"},{"id":"minecraft:waxed_oxidized_copper_door","localizedName":"Waxed Oxidized Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_door"},{"id":"minecraft:waxed_oxidized_copper_grate","localizedName":"Waxed Oxidized Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_grate"},{"id":"minecraft:waxed_oxidized_copper_trapdoor","localizedName":"Waxed Oxidized Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_trapdoor"},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper"},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_slab"},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_stairs"},{"id":"minecraft:waxed_weathered_chiseled_copper","localizedName":"Waxed Weathered Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_chiseled_copper"},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper"},{"id":"minecraft:waxed_weathered_copper_bulb","localizedName":"Waxed Weathered Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_bulb"},{"id":"minecraft:waxed_weathered_copper_door","localizedName":"Waxed Weathered Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_door"},{"id":"minecraft:waxed_weathered_copper_grate","localizedName":"Waxed Weathered Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_grate"},{"id":"minecraft:waxed_weathered_copper_trapdoor","localizedName":"Waxed Weathered Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_trapdoor"},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper"},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_slab"},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_stairs"},{"id":"minecraft:wayfinder_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.wayfinder_armor_trim_smithing_template"},{"id":"minecraft:weathered_chiseled_copper","localizedName":"Weathered Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_chiseled_copper"},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper"},{"id":"minecraft:weathered_copper_bulb","localizedName":"Weathered Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_bulb"},{"id":"minecraft:weathered_copper_door","localizedName":"Weathered Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_door"},{"id":"minecraft:weathered_copper_grate","localizedName":"Weathered Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_grate"},{"id":"minecraft:weathered_copper_trapdoor","localizedName":"Weathered Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_trapdoor"},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper"},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_slab"},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_stairs"},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.weeping_vines"},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","maxStackSize":64,"unlocalizedName":"block.minecraft.wet_sponge"},{"id":"minecraft:wheat","localizedName":"Wheat","maxStackSize":64,"unlocalizedName":"item.minecraft.wheat"},{"id":"minecraft:wheat_seeds","localizedName":"Wheat Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.wheat_seeds"},{"id":"minecraft:white_banner","localizedName":"White Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.white_banner"},{"id":"minecraft:white_bed","localizedName":"White Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.white_bed"},{"id":"minecraft:white_candle","localizedName":"White Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.white_candle"},{"id":"minecraft:white_carpet","localizedName":"White Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.white_carpet"},{"id":"minecraft:white_concrete","localizedName":"White Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete"},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete_powder"},{"id":"minecraft:white_dye","localizedName":"White Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.white_dye"},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.white_glazed_terracotta"},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.white_shulker_box"},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass"},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass_pane"},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.white_terracotta"},{"id":"minecraft:white_tulip","localizedName":"White Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.white_tulip"},{"id":"minecraft:white_wool","localizedName":"White Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.white_wool"},{"id":"minecraft:wild_armor_trim_smithing_template","localizedName":"Smithing Template","maxStackSize":64,"unlocalizedName":"item.minecraft.wild_armor_trim_smithing_template"},{"id":"minecraft:wind_charge","localizedName":"Wind Charge","maxStackSize":64,"unlocalizedName":"item.minecraft.wind_charge"},{"id":"minecraft:witch_spawn_egg","localizedName":"Witch Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.witch_spawn_egg"},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","maxStackSize":64,"unlocalizedName":"block.minecraft.wither_rose"},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxStackSize":64,"unlocalizedName":"block.minecraft.wither_skeleton_skull"},{"id":"minecraft:wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg"},{"id":"minecraft:wither_spawn_egg","localizedName":"Wither Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wither_spawn_egg"},{"id":"minecraft:wolf_armor","localizedName":"Wolf Armor","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.wolf_armor"},{"id":"minecraft:wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wolf_spawn_egg"},{"id":"minecraft:wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_axe"},{"id":"minecraft:wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_hoe"},{"id":"minecraft:wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_pickaxe"},{"id":"minecraft:wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_shovel"},{"id":"minecraft:wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_sword"},{"id":"minecraft:writable_book","localizedName":"Book and Quill","maxStackSize":1,"unlocalizedName":"item.minecraft.writable_book"},{"id":"minecraft:written_book","localizedName":"Written Book","maxStackSize":16,"unlocalizedName":"item.minecraft.written_book"},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.yellow_banner"},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_bed"},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_candle"},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_carpet"},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete"},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete_powder"},{"id":"minecraft:yellow_dye","localizedName":"Yellow Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.yellow_dye"},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_glazed_terracotta"},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_shulker_box"},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass"},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass_pane"},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_terracotta"},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_wool"},{"id":"minecraft:zoglin_spawn_egg","localizedName":"Zoglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zoglin_spawn_egg"},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","maxStackSize":64,"unlocalizedName":"block.minecraft.zombie_head"},{"id":"minecraft:zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_horse_spawn_egg"},{"id":"minecraft:zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_spawn_egg"},{"id":"minecraft:zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_villager_spawn_egg"},{"id":"minecraft:zombified_piglin_spawn_egg","localizedName":"Zombified Piglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombified_piglin_spawn_egg"}] \ No newline at end of file diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.1213.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.1213.json new file mode 100644 index 000000000..bfa6c7439 --- /dev/null +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/items.1213.json @@ -0,0 +1 @@ +[{"id":"minecraft:acacia_boat","localizedName":"Acacia Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_boat"},{"id":"minecraft:acacia_button","localizedName":"Acacia Button","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_button"},{"id":"minecraft:acacia_chest_boat","localizedName":"Acacia Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.acacia_chest_boat"},{"id":"minecraft:acacia_door","localizedName":"Acacia Door","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_door"},{"id":"minecraft:acacia_fence","localizedName":"Acacia Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence"},{"id":"minecraft:acacia_fence_gate","localizedName":"Acacia Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_fence_gate"},{"id":"minecraft:acacia_hanging_sign","localizedName":"Acacia Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_hanging_sign"},{"id":"minecraft:acacia_leaves","localizedName":"Acacia Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_leaves"},{"id":"minecraft:acacia_log","localizedName":"Acacia Log","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_log"},{"id":"minecraft:acacia_planks","localizedName":"Acacia Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_planks"},{"id":"minecraft:acacia_pressure_plate","localizedName":"Acacia Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_pressure_plate"},{"id":"minecraft:acacia_sapling","localizedName":"Acacia Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_sapling"},{"id":"minecraft:acacia_sign","localizedName":"Acacia Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.acacia_sign"},{"id":"minecraft:acacia_slab","localizedName":"Acacia Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_slab"},{"id":"minecraft:acacia_stairs","localizedName":"Acacia Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_stairs"},{"id":"minecraft:acacia_trapdoor","localizedName":"Acacia Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_trapdoor"},{"id":"minecraft:acacia_wood","localizedName":"Acacia Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.acacia_wood"},{"id":"minecraft:activator_rail","localizedName":"Activator Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.activator_rail"},{"id":"minecraft:air","localizedName":"Air","maxStackSize":64,"unlocalizedName":"block.minecraft.air"},{"id":"minecraft:allay_spawn_egg","localizedName":"Allay Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.allay_spawn_egg"},{"id":"minecraft:allium","localizedName":"Allium","maxStackSize":64,"unlocalizedName":"block.minecraft.allium"},{"id":"minecraft:amethyst_block","localizedName":"Block of Amethyst","maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_block"},{"id":"minecraft:amethyst_cluster","localizedName":"Amethyst Cluster","maxStackSize":64,"unlocalizedName":"block.minecraft.amethyst_cluster"},{"id":"minecraft:amethyst_shard","localizedName":"Amethyst Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.amethyst_shard"},{"id":"minecraft:ancient_debris","localizedName":"Ancient Debris","maxStackSize":64,"unlocalizedName":"block.minecraft.ancient_debris"},{"id":"minecraft:andesite","localizedName":"Andesite","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite"},{"id":"minecraft:andesite_slab","localizedName":"Andesite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_slab"},{"id":"minecraft:andesite_stairs","localizedName":"Andesite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_stairs"},{"id":"minecraft:andesite_wall","localizedName":"Andesite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.andesite_wall"},{"id":"minecraft:angler_pottery_sherd","localizedName":"Angler Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.angler_pottery_sherd"},{"id":"minecraft:anvil","localizedName":"Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.anvil"},{"id":"minecraft:apple","localizedName":"Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.apple"},{"id":"minecraft:archer_pottery_sherd","localizedName":"Archer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.archer_pottery_sherd"},{"id":"minecraft:armadillo_scute","localizedName":"Armadillo Scute","maxStackSize":64,"unlocalizedName":"item.minecraft.armadillo_scute"},{"id":"minecraft:armadillo_spawn_egg","localizedName":"Armadillo Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.armadillo_spawn_egg"},{"id":"minecraft:armor_stand","localizedName":"Armor Stand","maxStackSize":16,"unlocalizedName":"item.minecraft.armor_stand"},{"id":"minecraft:arms_up_pottery_sherd","localizedName":"Arms Up Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.arms_up_pottery_sherd"},{"id":"minecraft:arrow","localizedName":"Arrow","maxStackSize":64,"unlocalizedName":"item.minecraft.arrow"},{"id":"minecraft:axolotl_bucket","localizedName":"Bucket of Axolotl","maxStackSize":1,"unlocalizedName":"item.minecraft.axolotl_bucket"},{"id":"minecraft:axolotl_spawn_egg","localizedName":"Axolotl Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.axolotl_spawn_egg"},{"id":"minecraft:azalea","localizedName":"Azalea","maxStackSize":64,"unlocalizedName":"block.minecraft.azalea"},{"id":"minecraft:azalea_leaves","localizedName":"Azalea Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.azalea_leaves"},{"id":"minecraft:azure_bluet","localizedName":"Azure Bluet","maxStackSize":64,"unlocalizedName":"block.minecraft.azure_bluet"},{"id":"minecraft:baked_potato","localizedName":"Baked Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.baked_potato"},{"id":"minecraft:bamboo","localizedName":"Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo"},{"id":"minecraft:bamboo_block","localizedName":"Block of Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_block"},{"id":"minecraft:bamboo_button","localizedName":"Bamboo Button","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_button"},{"id":"minecraft:bamboo_chest_raft","localizedName":"Bamboo Raft with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.bamboo_chest_raft"},{"id":"minecraft:bamboo_door","localizedName":"Bamboo Door","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_door"},{"id":"minecraft:bamboo_fence","localizedName":"Bamboo Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_fence"},{"id":"minecraft:bamboo_fence_gate","localizedName":"Bamboo Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_fence_gate"},{"id":"minecraft:bamboo_hanging_sign","localizedName":"Bamboo Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.bamboo_hanging_sign"},{"id":"minecraft:bamboo_mosaic","localizedName":"Bamboo Mosaic","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic"},{"id":"minecraft:bamboo_mosaic_slab","localizedName":"Bamboo Mosaic Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic_slab"},{"id":"minecraft:bamboo_mosaic_stairs","localizedName":"Bamboo Mosaic Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_mosaic_stairs"},{"id":"minecraft:bamboo_planks","localizedName":"Bamboo Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_planks"},{"id":"minecraft:bamboo_pressure_plate","localizedName":"Bamboo Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_pressure_plate"},{"id":"minecraft:bamboo_raft","localizedName":"Bamboo Raft","maxStackSize":1,"unlocalizedName":"item.minecraft.bamboo_raft"},{"id":"minecraft:bamboo_sign","localizedName":"Bamboo Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.bamboo_sign"},{"id":"minecraft:bamboo_slab","localizedName":"Bamboo Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_slab"},{"id":"minecraft:bamboo_stairs","localizedName":"Bamboo Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_stairs"},{"id":"minecraft:bamboo_trapdoor","localizedName":"Bamboo Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.bamboo_trapdoor"},{"id":"minecraft:barrel","localizedName":"Barrel","maxStackSize":64,"unlocalizedName":"block.minecraft.barrel"},{"id":"minecraft:barrier","localizedName":"Barrier","maxStackSize":64,"unlocalizedName":"block.minecraft.barrier"},{"id":"minecraft:basalt","localizedName":"Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.basalt"},{"id":"minecraft:bat_spawn_egg","localizedName":"Bat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bat_spawn_egg"},{"id":"minecraft:beacon","localizedName":"Beacon","maxStackSize":64,"unlocalizedName":"block.minecraft.beacon"},{"id":"minecraft:bedrock","localizedName":"Bedrock","maxStackSize":64,"unlocalizedName":"block.minecraft.bedrock"},{"id":"minecraft:bee_nest","localizedName":"Bee Nest","maxStackSize":64,"unlocalizedName":"block.minecraft.bee_nest"},{"id":"minecraft:bee_spawn_egg","localizedName":"Bee Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bee_spawn_egg"},{"id":"minecraft:beef","localizedName":"Raw Beef","maxStackSize":64,"unlocalizedName":"item.minecraft.beef"},{"id":"minecraft:beehive","localizedName":"Beehive","maxStackSize":64,"unlocalizedName":"block.minecraft.beehive"},{"id":"minecraft:beetroot","localizedName":"Beetroot","maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot"},{"id":"minecraft:beetroot_seeds","localizedName":"Beetroot Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.beetroot_seeds"},{"id":"minecraft:beetroot_soup","localizedName":"Beetroot Soup","maxStackSize":1,"unlocalizedName":"item.minecraft.beetroot_soup"},{"id":"minecraft:bell","localizedName":"Bell","maxStackSize":64,"unlocalizedName":"block.minecraft.bell"},{"id":"minecraft:big_dripleaf","localizedName":"Big Dripleaf","maxStackSize":64,"unlocalizedName":"block.minecraft.big_dripleaf"},{"id":"minecraft:birch_boat","localizedName":"Birch Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.birch_boat"},{"id":"minecraft:birch_button","localizedName":"Birch Button","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_button"},{"id":"minecraft:birch_chest_boat","localizedName":"Birch Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.birch_chest_boat"},{"id":"minecraft:birch_door","localizedName":"Birch Door","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_door"},{"id":"minecraft:birch_fence","localizedName":"Birch Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence"},{"id":"minecraft:birch_fence_gate","localizedName":"Birch Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_fence_gate"},{"id":"minecraft:birch_hanging_sign","localizedName":"Birch Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.birch_hanging_sign"},{"id":"minecraft:birch_leaves","localizedName":"Birch Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_leaves"},{"id":"minecraft:birch_log","localizedName":"Birch Log","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_log"},{"id":"minecraft:birch_planks","localizedName":"Birch Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_planks"},{"id":"minecraft:birch_pressure_plate","localizedName":"Birch Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_pressure_plate"},{"id":"minecraft:birch_sapling","localizedName":"Birch Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_sapling"},{"id":"minecraft:birch_sign","localizedName":"Birch Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.birch_sign"},{"id":"minecraft:birch_slab","localizedName":"Birch Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_slab"},{"id":"minecraft:birch_stairs","localizedName":"Birch Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_stairs"},{"id":"minecraft:birch_trapdoor","localizedName":"Birch Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_trapdoor"},{"id":"minecraft:birch_wood","localizedName":"Birch Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.birch_wood"},{"id":"minecraft:black_banner","localizedName":"Black Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.black_banner"},{"id":"minecraft:black_bed","localizedName":"Black Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.black_bed"},{"id":"minecraft:black_bundle","localizedName":"Black Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.black_bundle"},{"id":"minecraft:black_candle","localizedName":"Black Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.black_candle"},{"id":"minecraft:black_carpet","localizedName":"Black Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.black_carpet"},{"id":"minecraft:black_concrete","localizedName":"Black Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete"},{"id":"minecraft:black_concrete_powder","localizedName":"Black Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.black_concrete_powder"},{"id":"minecraft:black_dye","localizedName":"Black Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.black_dye"},{"id":"minecraft:black_glazed_terracotta","localizedName":"Black Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.black_glazed_terracotta"},{"id":"minecraft:black_shulker_box","localizedName":"Black Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.black_shulker_box"},{"id":"minecraft:black_stained_glass","localizedName":"Black Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass"},{"id":"minecraft:black_stained_glass_pane","localizedName":"Black Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.black_stained_glass_pane"},{"id":"minecraft:black_terracotta","localizedName":"Black Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.black_terracotta"},{"id":"minecraft:black_wool","localizedName":"Black Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.black_wool"},{"id":"minecraft:blackstone","localizedName":"Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone"},{"id":"minecraft:blackstone_slab","localizedName":"Blackstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_slab"},{"id":"minecraft:blackstone_stairs","localizedName":"Blackstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_stairs"},{"id":"minecraft:blackstone_wall","localizedName":"Blackstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.blackstone_wall"},{"id":"minecraft:blade_pottery_sherd","localizedName":"Blade Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.blade_pottery_sherd"},{"id":"minecraft:blast_furnace","localizedName":"Blast Furnace","maxStackSize":64,"unlocalizedName":"block.minecraft.blast_furnace"},{"id":"minecraft:blaze_powder","localizedName":"Blaze Powder","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_powder"},{"id":"minecraft:blaze_rod","localizedName":"Blaze Rod","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_rod"},{"id":"minecraft:blaze_spawn_egg","localizedName":"Blaze Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.blaze_spawn_egg"},{"id":"minecraft:blue_banner","localizedName":"Blue Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.blue_banner"},{"id":"minecraft:blue_bed","localizedName":"Blue Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.blue_bed"},{"id":"minecraft:blue_bundle","localizedName":"Blue Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.blue_bundle"},{"id":"minecraft:blue_candle","localizedName":"Blue Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_candle"},{"id":"minecraft:blue_carpet","localizedName":"Blue Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_carpet"},{"id":"minecraft:blue_concrete","localizedName":"Blue Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete"},{"id":"minecraft:blue_concrete_powder","localizedName":"Blue Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_concrete_powder"},{"id":"minecraft:blue_dye","localizedName":"Blue Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.blue_dye"},{"id":"minecraft:blue_glazed_terracotta","localizedName":"Blue Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_glazed_terracotta"},{"id":"minecraft:blue_ice","localizedName":"Blue Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_ice"},{"id":"minecraft:blue_orchid","localizedName":"Blue Orchid","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_orchid"},{"id":"minecraft:blue_shulker_box","localizedName":"Blue Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.blue_shulker_box"},{"id":"minecraft:blue_stained_glass","localizedName":"Blue Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass"},{"id":"minecraft:blue_stained_glass_pane","localizedName":"Blue Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_stained_glass_pane"},{"id":"minecraft:blue_terracotta","localizedName":"Blue Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_terracotta"},{"id":"minecraft:blue_wool","localizedName":"Blue Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.blue_wool"},{"id":"minecraft:bogged_spawn_egg","localizedName":"Bogged Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.bogged_spawn_egg"},{"id":"minecraft:bolt_armor_trim_smithing_template","localizedName":"Bolt Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.bolt_armor_trim_smithing_template"},{"id":"minecraft:bone","localizedName":"Bone","maxStackSize":64,"unlocalizedName":"item.minecraft.bone"},{"id":"minecraft:bone_block","localizedName":"Bone Block","maxStackSize":64,"unlocalizedName":"block.minecraft.bone_block"},{"id":"minecraft:bone_meal","localizedName":"Bone Meal","maxStackSize":64,"unlocalizedName":"item.minecraft.bone_meal"},{"id":"minecraft:book","localizedName":"Book","maxStackSize":64,"unlocalizedName":"item.minecraft.book"},{"id":"minecraft:bookshelf","localizedName":"Bookshelf","maxStackSize":64,"unlocalizedName":"block.minecraft.bookshelf"},{"id":"minecraft:bordure_indented_banner_pattern","localizedName":"Bordure Indented Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.bordure_indented_banner_pattern"},{"id":"minecraft:bow","localizedName":"Bow","maxDamage":384,"maxStackSize":1,"unlocalizedName":"item.minecraft.bow"},{"id":"minecraft:bowl","localizedName":"Bowl","maxStackSize":64,"unlocalizedName":"item.minecraft.bowl"},{"id":"minecraft:brain_coral","localizedName":"Brain Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral"},{"id":"minecraft:brain_coral_block","localizedName":"Brain Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_block"},{"id":"minecraft:brain_coral_fan","localizedName":"Brain Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.brain_coral_fan"},{"id":"minecraft:bread","localizedName":"Bread","maxStackSize":64,"unlocalizedName":"item.minecraft.bread"},{"id":"minecraft:breeze_rod","localizedName":"Breeze Rod","maxStackSize":64,"unlocalizedName":"item.minecraft.breeze_rod"},{"id":"minecraft:breeze_spawn_egg","localizedName":"Breeze Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.breeze_spawn_egg"},{"id":"minecraft:brewer_pottery_sherd","localizedName":"Brewer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.brewer_pottery_sherd"},{"id":"minecraft:brewing_stand","localizedName":"Brewing Stand","maxStackSize":64,"unlocalizedName":"block.minecraft.brewing_stand"},{"id":"minecraft:brick","localizedName":"Brick","maxStackSize":64,"unlocalizedName":"item.minecraft.brick"},{"id":"minecraft:brick_slab","localizedName":"Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_slab"},{"id":"minecraft:brick_stairs","localizedName":"Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_stairs"},{"id":"minecraft:brick_wall","localizedName":"Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.brick_wall"},{"id":"minecraft:bricks","localizedName":"Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.bricks"},{"id":"minecraft:brown_banner","localizedName":"Brown Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.brown_banner"},{"id":"minecraft:brown_bed","localizedName":"Brown Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.brown_bed"},{"id":"minecraft:brown_bundle","localizedName":"Brown Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.brown_bundle"},{"id":"minecraft:brown_candle","localizedName":"Brown Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_candle"},{"id":"minecraft:brown_carpet","localizedName":"Brown Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_carpet"},{"id":"minecraft:brown_concrete","localizedName":"Brown Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete"},{"id":"minecraft:brown_concrete_powder","localizedName":"Brown Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_concrete_powder"},{"id":"minecraft:brown_dye","localizedName":"Brown Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.brown_dye"},{"id":"minecraft:brown_glazed_terracotta","localizedName":"Brown Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_glazed_terracotta"},{"id":"minecraft:brown_mushroom","localizedName":"Brown Mushroom","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom"},{"id":"minecraft:brown_mushroom_block","localizedName":"Brown Mushroom Block","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_mushroom_block"},{"id":"minecraft:brown_shulker_box","localizedName":"Brown Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.brown_shulker_box"},{"id":"minecraft:brown_stained_glass","localizedName":"Brown Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass"},{"id":"minecraft:brown_stained_glass_pane","localizedName":"Brown Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_stained_glass_pane"},{"id":"minecraft:brown_terracotta","localizedName":"Brown Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_terracotta"},{"id":"minecraft:brown_wool","localizedName":"Brown Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.brown_wool"},{"id":"minecraft:brush","localizedName":"Brush","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.brush"},{"id":"minecraft:bubble_coral","localizedName":"Bubble Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral"},{"id":"minecraft:bubble_coral_block","localizedName":"Bubble Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_block"},{"id":"minecraft:bubble_coral_fan","localizedName":"Bubble Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.bubble_coral_fan"},{"id":"minecraft:bucket","localizedName":"Bucket","maxStackSize":16,"unlocalizedName":"item.minecraft.bucket"},{"id":"minecraft:budding_amethyst","localizedName":"Budding Amethyst","maxStackSize":64,"unlocalizedName":"block.minecraft.budding_amethyst"},{"id":"minecraft:bundle","localizedName":"Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.bundle"},{"id":"minecraft:burn_pottery_sherd","localizedName":"Burn Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.burn_pottery_sherd"},{"id":"minecraft:cactus","localizedName":"Cactus","maxStackSize":64,"unlocalizedName":"block.minecraft.cactus"},{"id":"minecraft:cake","localizedName":"Cake","maxStackSize":1,"unlocalizedName":"block.minecraft.cake"},{"id":"minecraft:calcite","localizedName":"Calcite","maxStackSize":64,"unlocalizedName":"block.minecraft.calcite"},{"id":"minecraft:calibrated_sculk_sensor","localizedName":"Calibrated Sculk Sensor","maxStackSize":64,"unlocalizedName":"block.minecraft.calibrated_sculk_sensor"},{"id":"minecraft:camel_spawn_egg","localizedName":"Camel Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.camel_spawn_egg"},{"id":"minecraft:campfire","localizedName":"Campfire","maxStackSize":64,"unlocalizedName":"block.minecraft.campfire"},{"id":"minecraft:candle","localizedName":"Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.candle"},{"id":"minecraft:carrot","localizedName":"Carrot","maxStackSize":64,"unlocalizedName":"item.minecraft.carrot"},{"id":"minecraft:carrot_on_a_stick","localizedName":"Carrot on a Stick","maxDamage":25,"maxStackSize":1,"unlocalizedName":"item.minecraft.carrot_on_a_stick"},{"id":"minecraft:cartography_table","localizedName":"Cartography Table","maxStackSize":64,"unlocalizedName":"block.minecraft.cartography_table"},{"id":"minecraft:carved_pumpkin","localizedName":"Carved Pumpkin","maxStackSize":64,"unlocalizedName":"block.minecraft.carved_pumpkin"},{"id":"minecraft:cat_spawn_egg","localizedName":"Cat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cat_spawn_egg"},{"id":"minecraft:cauldron","localizedName":"Cauldron","maxStackSize":64,"unlocalizedName":"block.minecraft.cauldron"},{"id":"minecraft:cave_spider_spawn_egg","localizedName":"Cave Spider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cave_spider_spawn_egg"},{"id":"minecraft:chain","localizedName":"Chain","maxStackSize":64,"unlocalizedName":"block.minecraft.chain"},{"id":"minecraft:chain_command_block","localizedName":"Chain Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.chain_command_block"},{"id":"minecraft:chainmail_boots","localizedName":"Chainmail Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_boots"},{"id":"minecraft:chainmail_chestplate","localizedName":"Chainmail Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_chestplate"},{"id":"minecraft:chainmail_helmet","localizedName":"Chainmail Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_helmet"},{"id":"minecraft:chainmail_leggings","localizedName":"Chainmail Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.chainmail_leggings"},{"id":"minecraft:charcoal","localizedName":"Charcoal","maxStackSize":64,"unlocalizedName":"item.minecraft.charcoal"},{"id":"minecraft:cherry_boat","localizedName":"Cherry Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.cherry_boat"},{"id":"minecraft:cherry_button","localizedName":"Cherry Button","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_button"},{"id":"minecraft:cherry_chest_boat","localizedName":"Cherry Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.cherry_chest_boat"},{"id":"minecraft:cherry_door","localizedName":"Cherry Door","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_door"},{"id":"minecraft:cherry_fence","localizedName":"Cherry Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_fence"},{"id":"minecraft:cherry_fence_gate","localizedName":"Cherry Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_fence_gate"},{"id":"minecraft:cherry_hanging_sign","localizedName":"Cherry Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.cherry_hanging_sign"},{"id":"minecraft:cherry_leaves","localizedName":"Cherry Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_leaves"},{"id":"minecraft:cherry_log","localizedName":"Cherry Log","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_log"},{"id":"minecraft:cherry_planks","localizedName":"Cherry Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_planks"},{"id":"minecraft:cherry_pressure_plate","localizedName":"Cherry Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_pressure_plate"},{"id":"minecraft:cherry_sapling","localizedName":"Cherry Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_sapling"},{"id":"minecraft:cherry_sign","localizedName":"Cherry Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.cherry_sign"},{"id":"minecraft:cherry_slab","localizedName":"Cherry Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_slab"},{"id":"minecraft:cherry_stairs","localizedName":"Cherry Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_stairs"},{"id":"minecraft:cherry_trapdoor","localizedName":"Cherry Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_trapdoor"},{"id":"minecraft:cherry_wood","localizedName":"Cherry Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.cherry_wood"},{"id":"minecraft:chest","localizedName":"Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.chest"},{"id":"minecraft:chest_minecart","localizedName":"Minecart with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.chest_minecart"},{"id":"minecraft:chicken","localizedName":"Raw Chicken","maxStackSize":64,"unlocalizedName":"item.minecraft.chicken"},{"id":"minecraft:chicken_spawn_egg","localizedName":"Chicken Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.chicken_spawn_egg"},{"id":"minecraft:chipped_anvil","localizedName":"Chipped Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.chipped_anvil"},{"id":"minecraft:chiseled_bookshelf","localizedName":"Chiseled Bookshelf","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_bookshelf"},{"id":"minecraft:chiseled_copper","localizedName":"Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_copper"},{"id":"minecraft:chiseled_deepslate","localizedName":"Chiseled Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_deepslate"},{"id":"minecraft:chiseled_nether_bricks","localizedName":"Chiseled Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_nether_bricks"},{"id":"minecraft:chiseled_polished_blackstone","localizedName":"Chiseled Polished Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_polished_blackstone"},{"id":"minecraft:chiseled_quartz_block","localizedName":"Chiseled Quartz Block","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_quartz_block"},{"id":"minecraft:chiseled_red_sandstone","localizedName":"Chiseled Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_red_sandstone"},{"id":"minecraft:chiseled_sandstone","localizedName":"Chiseled Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_sandstone"},{"id":"minecraft:chiseled_stone_bricks","localizedName":"Chiseled Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_stone_bricks"},{"id":"minecraft:chiseled_tuff","localizedName":"Chiseled Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_tuff"},{"id":"minecraft:chiseled_tuff_bricks","localizedName":"Chiseled Tuff Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.chiseled_tuff_bricks"},{"id":"minecraft:chorus_flower","localizedName":"Chorus Flower","maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_flower"},{"id":"minecraft:chorus_fruit","localizedName":"Chorus Fruit","maxStackSize":64,"unlocalizedName":"item.minecraft.chorus_fruit"},{"id":"minecraft:chorus_plant","localizedName":"Chorus Plant","maxStackSize":64,"unlocalizedName":"block.minecraft.chorus_plant"},{"id":"minecraft:clay","localizedName":"Clay","maxStackSize":64,"unlocalizedName":"block.minecraft.clay"},{"id":"minecraft:clay_ball","localizedName":"Clay Ball","maxStackSize":64,"unlocalizedName":"item.minecraft.clay_ball"},{"id":"minecraft:clock","localizedName":"Clock","maxStackSize":64,"unlocalizedName":"item.minecraft.clock"},{"id":"minecraft:coal","localizedName":"Coal","maxStackSize":64,"unlocalizedName":"item.minecraft.coal"},{"id":"minecraft:coal_block","localizedName":"Block of Coal","maxStackSize":64,"unlocalizedName":"block.minecraft.coal_block"},{"id":"minecraft:coal_ore","localizedName":"Coal Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.coal_ore"},{"id":"minecraft:coarse_dirt","localizedName":"Coarse Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.coarse_dirt"},{"id":"minecraft:coast_armor_trim_smithing_template","localizedName":"Coast Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.coast_armor_trim_smithing_template"},{"id":"minecraft:cobbled_deepslate","localizedName":"Cobbled Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate"},{"id":"minecraft:cobbled_deepslate_slab","localizedName":"Cobbled Deepslate Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_slab"},{"id":"minecraft:cobbled_deepslate_stairs","localizedName":"Cobbled Deepslate Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_stairs"},{"id":"minecraft:cobbled_deepslate_wall","localizedName":"Cobbled Deepslate Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.cobbled_deepslate_wall"},{"id":"minecraft:cobblestone","localizedName":"Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone"},{"id":"minecraft:cobblestone_slab","localizedName":"Cobblestone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_slab"},{"id":"minecraft:cobblestone_stairs","localizedName":"Cobblestone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_stairs"},{"id":"minecraft:cobblestone_wall","localizedName":"Cobblestone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.cobblestone_wall"},{"id":"minecraft:cobweb","localizedName":"Cobweb","maxStackSize":64,"unlocalizedName":"block.minecraft.cobweb"},{"id":"minecraft:cocoa_beans","localizedName":"Cocoa Beans","maxStackSize":64,"unlocalizedName":"item.minecraft.cocoa_beans"},{"id":"minecraft:cod","localizedName":"Raw Cod","maxStackSize":64,"unlocalizedName":"item.minecraft.cod"},{"id":"minecraft:cod_bucket","localizedName":"Bucket of Cod","maxStackSize":1,"unlocalizedName":"item.minecraft.cod_bucket"},{"id":"minecraft:cod_spawn_egg","localizedName":"Cod Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cod_spawn_egg"},{"id":"minecraft:command_block","localizedName":"Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.command_block"},{"id":"minecraft:command_block_minecart","localizedName":"Minecart with Command Block","maxStackSize":1,"unlocalizedName":"item.minecraft.command_block_minecart"},{"id":"minecraft:comparator","localizedName":"Redstone Comparator","maxStackSize":64,"unlocalizedName":"block.minecraft.comparator"},{"id":"minecraft:compass","localizedName":"Compass","maxStackSize":64,"unlocalizedName":"item.minecraft.compass"},{"id":"minecraft:composter","localizedName":"Composter","maxStackSize":64,"unlocalizedName":"block.minecraft.composter"},{"id":"minecraft:conduit","localizedName":"Conduit","maxStackSize":64,"unlocalizedName":"block.minecraft.conduit"},{"id":"minecraft:cooked_beef","localizedName":"Steak","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_beef"},{"id":"minecraft:cooked_chicken","localizedName":"Cooked Chicken","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_chicken"},{"id":"minecraft:cooked_cod","localizedName":"Cooked Cod","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_cod"},{"id":"minecraft:cooked_mutton","localizedName":"Cooked Mutton","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_mutton"},{"id":"minecraft:cooked_porkchop","localizedName":"Cooked Porkchop","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_porkchop"},{"id":"minecraft:cooked_rabbit","localizedName":"Cooked Rabbit","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_rabbit"},{"id":"minecraft:cooked_salmon","localizedName":"Cooked Salmon","maxStackSize":64,"unlocalizedName":"item.minecraft.cooked_salmon"},{"id":"minecraft:cookie","localizedName":"Cookie","maxStackSize":64,"unlocalizedName":"item.minecraft.cookie"},{"id":"minecraft:copper_block","localizedName":"Block of Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_block"},{"id":"minecraft:copper_bulb","localizedName":"Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_bulb"},{"id":"minecraft:copper_door","localizedName":"Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_door"},{"id":"minecraft:copper_grate","localizedName":"Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_grate"},{"id":"minecraft:copper_ingot","localizedName":"Copper Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.copper_ingot"},{"id":"minecraft:copper_ore","localizedName":"Copper Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_ore"},{"id":"minecraft:copper_trapdoor","localizedName":"Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.copper_trapdoor"},{"id":"minecraft:cornflower","localizedName":"Cornflower","maxStackSize":64,"unlocalizedName":"block.minecraft.cornflower"},{"id":"minecraft:cow_spawn_egg","localizedName":"Cow Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.cow_spawn_egg"},{"id":"minecraft:cracked_deepslate_bricks","localizedName":"Cracked Deepslate Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_bricks"},{"id":"minecraft:cracked_deepslate_tiles","localizedName":"Cracked Deepslate Tiles","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_deepslate_tiles"},{"id":"minecraft:cracked_nether_bricks","localizedName":"Cracked Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_nether_bricks"},{"id":"minecraft:cracked_polished_blackstone_bricks","localizedName":"Cracked Polished Blackstone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_polished_blackstone_bricks"},{"id":"minecraft:cracked_stone_bricks","localizedName":"Cracked Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.cracked_stone_bricks"},{"id":"minecraft:crafter","localizedName":"Crafter","maxStackSize":64,"unlocalizedName":"block.minecraft.crafter"},{"id":"minecraft:crafting_table","localizedName":"Crafting Table","maxStackSize":64,"unlocalizedName":"block.minecraft.crafting_table"},{"id":"minecraft:creaking_heart","localizedName":"Creaking Heart","maxStackSize":64,"unlocalizedName":"block.minecraft.creaking_heart"},{"id":"minecraft:creaking_spawn_egg","localizedName":"Creaking Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.creaking_spawn_egg"},{"id":"minecraft:creeper_banner_pattern","localizedName":"Creeper Charge Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.creeper_banner_pattern"},{"id":"minecraft:creeper_head","localizedName":"Creeper Head","maxStackSize":64,"unlocalizedName":"block.minecraft.creeper_head"},{"id":"minecraft:creeper_spawn_egg","localizedName":"Creeper Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.creeper_spawn_egg"},{"id":"minecraft:crimson_button","localizedName":"Crimson Button","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_button"},{"id":"minecraft:crimson_door","localizedName":"Crimson Door","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_door"},{"id":"minecraft:crimson_fence","localizedName":"Crimson Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence"},{"id":"minecraft:crimson_fence_gate","localizedName":"Crimson Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fence_gate"},{"id":"minecraft:crimson_fungus","localizedName":"Crimson Fungus","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_fungus"},{"id":"minecraft:crimson_hanging_sign","localizedName":"Crimson Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_hanging_sign"},{"id":"minecraft:crimson_hyphae","localizedName":"Crimson Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_hyphae"},{"id":"minecraft:crimson_nylium","localizedName":"Crimson Nylium","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_nylium"},{"id":"minecraft:crimson_planks","localizedName":"Crimson Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_planks"},{"id":"minecraft:crimson_pressure_plate","localizedName":"Crimson Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_pressure_plate"},{"id":"minecraft:crimson_roots","localizedName":"Crimson Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_roots"},{"id":"minecraft:crimson_sign","localizedName":"Crimson Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.crimson_sign"},{"id":"minecraft:crimson_slab","localizedName":"Crimson Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_slab"},{"id":"minecraft:crimson_stairs","localizedName":"Crimson Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stairs"},{"id":"minecraft:crimson_stem","localizedName":"Crimson Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_stem"},{"id":"minecraft:crimson_trapdoor","localizedName":"Crimson Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.crimson_trapdoor"},{"id":"minecraft:crossbow","localizedName":"Crossbow","maxDamage":465,"maxStackSize":1,"unlocalizedName":"item.minecraft.crossbow"},{"id":"minecraft:crying_obsidian","localizedName":"Crying Obsidian","maxStackSize":64,"unlocalizedName":"block.minecraft.crying_obsidian"},{"id":"minecraft:cut_copper","localizedName":"Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper"},{"id":"minecraft:cut_copper_slab","localizedName":"Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_slab"},{"id":"minecraft:cut_copper_stairs","localizedName":"Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_copper_stairs"},{"id":"minecraft:cut_red_sandstone","localizedName":"Cut Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone"},{"id":"minecraft:cut_red_sandstone_slab","localizedName":"Cut Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_red_sandstone_slab"},{"id":"minecraft:cut_sandstone","localizedName":"Cut Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone"},{"id":"minecraft:cut_sandstone_slab","localizedName":"Cut Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.cut_sandstone_slab"},{"id":"minecraft:cyan_banner","localizedName":"Cyan Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.cyan_banner"},{"id":"minecraft:cyan_bed","localizedName":"Cyan Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_bed"},{"id":"minecraft:cyan_bundle","localizedName":"Cyan Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.cyan_bundle"},{"id":"minecraft:cyan_candle","localizedName":"Cyan Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_candle"},{"id":"minecraft:cyan_carpet","localizedName":"Cyan Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_carpet"},{"id":"minecraft:cyan_concrete","localizedName":"Cyan Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete"},{"id":"minecraft:cyan_concrete_powder","localizedName":"Cyan Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_concrete_powder"},{"id":"minecraft:cyan_dye","localizedName":"Cyan Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.cyan_dye"},{"id":"minecraft:cyan_glazed_terracotta","localizedName":"Cyan Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_glazed_terracotta"},{"id":"minecraft:cyan_shulker_box","localizedName":"Cyan Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.cyan_shulker_box"},{"id":"minecraft:cyan_stained_glass","localizedName":"Cyan Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass"},{"id":"minecraft:cyan_stained_glass_pane","localizedName":"Cyan Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_stained_glass_pane"},{"id":"minecraft:cyan_terracotta","localizedName":"Cyan Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_terracotta"},{"id":"minecraft:cyan_wool","localizedName":"Cyan Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.cyan_wool"},{"id":"minecraft:damaged_anvil","localizedName":"Damaged Anvil","maxStackSize":64,"unlocalizedName":"block.minecraft.damaged_anvil"},{"id":"minecraft:dandelion","localizedName":"Dandelion","maxStackSize":64,"unlocalizedName":"block.minecraft.dandelion"},{"id":"minecraft:danger_pottery_sherd","localizedName":"Danger Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.danger_pottery_sherd"},{"id":"minecraft:dark_oak_boat","localizedName":"Dark Oak Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_boat"},{"id":"minecraft:dark_oak_button","localizedName":"Dark Oak Button","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_button"},{"id":"minecraft:dark_oak_chest_boat","localizedName":"Dark Oak Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.dark_oak_chest_boat"},{"id":"minecraft:dark_oak_door","localizedName":"Dark Oak Door","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_door"},{"id":"minecraft:dark_oak_fence","localizedName":"Dark Oak Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence"},{"id":"minecraft:dark_oak_fence_gate","localizedName":"Dark Oak Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_fence_gate"},{"id":"minecraft:dark_oak_hanging_sign","localizedName":"Dark Oak Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_hanging_sign"},{"id":"minecraft:dark_oak_leaves","localizedName":"Dark Oak Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_leaves"},{"id":"minecraft:dark_oak_log","localizedName":"Dark Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_log"},{"id":"minecraft:dark_oak_planks","localizedName":"Dark Oak Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_planks"},{"id":"minecraft:dark_oak_pressure_plate","localizedName":"Dark Oak Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_pressure_plate"},{"id":"minecraft:dark_oak_sapling","localizedName":"Dark Oak Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_sapling"},{"id":"minecraft:dark_oak_sign","localizedName":"Dark Oak Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.dark_oak_sign"},{"id":"minecraft:dark_oak_slab","localizedName":"Dark Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_slab"},{"id":"minecraft:dark_oak_stairs","localizedName":"Dark Oak Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_stairs"},{"id":"minecraft:dark_oak_trapdoor","localizedName":"Dark Oak Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_trapdoor"},{"id":"minecraft:dark_oak_wood","localizedName":"Dark Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_oak_wood"},{"id":"minecraft:dark_prismarine","localizedName":"Dark Prismarine","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine"},{"id":"minecraft:dark_prismarine_slab","localizedName":"Dark Prismarine Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_slab"},{"id":"minecraft:dark_prismarine_stairs","localizedName":"Dark Prismarine Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.dark_prismarine_stairs"},{"id":"minecraft:daylight_detector","localizedName":"Daylight Detector","maxStackSize":64,"unlocalizedName":"block.minecraft.daylight_detector"},{"id":"minecraft:dead_brain_coral","localizedName":"Dead Brain Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral"},{"id":"minecraft:dead_brain_coral_block","localizedName":"Dead Brain Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_block"},{"id":"minecraft:dead_brain_coral_fan","localizedName":"Dead Brain Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_brain_coral_fan"},{"id":"minecraft:dead_bubble_coral","localizedName":"Dead Bubble Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral"},{"id":"minecraft:dead_bubble_coral_block","localizedName":"Dead Bubble Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_block"},{"id":"minecraft:dead_bubble_coral_fan","localizedName":"Dead Bubble Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bubble_coral_fan"},{"id":"minecraft:dead_bush","localizedName":"Dead Bush","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_bush"},{"id":"minecraft:dead_fire_coral","localizedName":"Dead Fire Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral"},{"id":"minecraft:dead_fire_coral_block","localizedName":"Dead Fire Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_block"},{"id":"minecraft:dead_fire_coral_fan","localizedName":"Dead Fire Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_fire_coral_fan"},{"id":"minecraft:dead_horn_coral","localizedName":"Dead Horn Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral"},{"id":"minecraft:dead_horn_coral_block","localizedName":"Dead Horn Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_block"},{"id":"minecraft:dead_horn_coral_fan","localizedName":"Dead Horn Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_horn_coral_fan"},{"id":"minecraft:dead_tube_coral","localizedName":"Dead Tube Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral"},{"id":"minecraft:dead_tube_coral_block","localizedName":"Dead Tube Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_block"},{"id":"minecraft:dead_tube_coral_fan","localizedName":"Dead Tube Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.dead_tube_coral_fan"},{"id":"minecraft:debug_stick","localizedName":"Debug Stick","maxStackSize":1,"unlocalizedName":"item.minecraft.debug_stick"},{"id":"minecraft:decorated_pot","localizedName":"Decorated Pot","maxStackSize":64,"unlocalizedName":"block.minecraft.decorated_pot"},{"id":"minecraft:deepslate","localizedName":"Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate"},{"id":"minecraft:deepslate_brick_slab","localizedName":"Deepslate Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_slab"},{"id":"minecraft:deepslate_brick_stairs","localizedName":"Deepslate Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_stairs"},{"id":"minecraft:deepslate_brick_wall","localizedName":"Deepslate Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_brick_wall"},{"id":"minecraft:deepslate_bricks","localizedName":"Deepslate Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_bricks"},{"id":"minecraft:deepslate_coal_ore","localizedName":"Deepslate Coal Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_coal_ore"},{"id":"minecraft:deepslate_copper_ore","localizedName":"Deepslate Copper Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_copper_ore"},{"id":"minecraft:deepslate_diamond_ore","localizedName":"Deepslate Diamond Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_diamond_ore"},{"id":"minecraft:deepslate_emerald_ore","localizedName":"Deepslate Emerald Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_emerald_ore"},{"id":"minecraft:deepslate_gold_ore","localizedName":"Deepslate Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_gold_ore"},{"id":"minecraft:deepslate_iron_ore","localizedName":"Deepslate Iron Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_iron_ore"},{"id":"minecraft:deepslate_lapis_ore","localizedName":"Deepslate Lapis Lazuli Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_lapis_ore"},{"id":"minecraft:deepslate_redstone_ore","localizedName":"Deepslate Redstone Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_redstone_ore"},{"id":"minecraft:deepslate_tile_slab","localizedName":"Deepslate Tile Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_slab"},{"id":"minecraft:deepslate_tile_stairs","localizedName":"Deepslate Tile Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_stairs"},{"id":"minecraft:deepslate_tile_wall","localizedName":"Deepslate Tile Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tile_wall"},{"id":"minecraft:deepslate_tiles","localizedName":"Deepslate Tiles","maxStackSize":64,"unlocalizedName":"block.minecraft.deepslate_tiles"},{"id":"minecraft:detector_rail","localizedName":"Detector Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.detector_rail"},{"id":"minecraft:diamond","localizedName":"Diamond","maxStackSize":64,"unlocalizedName":"item.minecraft.diamond"},{"id":"minecraft:diamond_axe","localizedName":"Diamond Axe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_axe"},{"id":"minecraft:diamond_block","localizedName":"Block of Diamond","maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_block"},{"id":"minecraft:diamond_boots","localizedName":"Diamond Boots","maxDamage":429,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_boots"},{"id":"minecraft:diamond_chestplate","localizedName":"Diamond Chestplate","maxDamage":528,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_chestplate"},{"id":"minecraft:diamond_helmet","localizedName":"Diamond Helmet","maxDamage":363,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_helmet"},{"id":"minecraft:diamond_hoe","localizedName":"Diamond Hoe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_hoe"},{"id":"minecraft:diamond_horse_armor","localizedName":"Diamond Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_horse_armor"},{"id":"minecraft:diamond_leggings","localizedName":"Diamond Leggings","maxDamage":495,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_leggings"},{"id":"minecraft:diamond_ore","localizedName":"Diamond Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.diamond_ore"},{"id":"minecraft:diamond_pickaxe","localizedName":"Diamond Pickaxe","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_pickaxe"},{"id":"minecraft:diamond_shovel","localizedName":"Diamond Shovel","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_shovel"},{"id":"minecraft:diamond_sword","localizedName":"Diamond Sword","maxDamage":1561,"maxStackSize":1,"unlocalizedName":"item.minecraft.diamond_sword"},{"id":"minecraft:diorite","localizedName":"Diorite","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite"},{"id":"minecraft:diorite_slab","localizedName":"Diorite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_slab"},{"id":"minecraft:diorite_stairs","localizedName":"Diorite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_stairs"},{"id":"minecraft:diorite_wall","localizedName":"Diorite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.diorite_wall"},{"id":"minecraft:dirt","localizedName":"Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.dirt"},{"id":"minecraft:dirt_path","localizedName":"Dirt Path","maxStackSize":64,"unlocalizedName":"block.minecraft.dirt_path"},{"id":"minecraft:disc_fragment_5","localizedName":"Disc Fragment","maxStackSize":64,"unlocalizedName":"item.minecraft.disc_fragment_5"},{"id":"minecraft:dispenser","localizedName":"Dispenser","maxStackSize":64,"unlocalizedName":"block.minecraft.dispenser"},{"id":"minecraft:dolphin_spawn_egg","localizedName":"Dolphin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.dolphin_spawn_egg"},{"id":"minecraft:donkey_spawn_egg","localizedName":"Donkey Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.donkey_spawn_egg"},{"id":"minecraft:dragon_breath","localizedName":"Dragon\u0027s Breath","maxStackSize":64,"unlocalizedName":"item.minecraft.dragon_breath"},{"id":"minecraft:dragon_egg","localizedName":"Dragon Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_egg"},{"id":"minecraft:dragon_head","localizedName":"Dragon Head","maxStackSize":64,"unlocalizedName":"block.minecraft.dragon_head"},{"id":"minecraft:dried_kelp","localizedName":"Dried Kelp","maxStackSize":64,"unlocalizedName":"item.minecraft.dried_kelp"},{"id":"minecraft:dried_kelp_block","localizedName":"Dried Kelp Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dried_kelp_block"},{"id":"minecraft:dripstone_block","localizedName":"Dripstone Block","maxStackSize":64,"unlocalizedName":"block.minecraft.dripstone_block"},{"id":"minecraft:dropper","localizedName":"Dropper","maxStackSize":64,"unlocalizedName":"block.minecraft.dropper"},{"id":"minecraft:drowned_spawn_egg","localizedName":"Drowned Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.drowned_spawn_egg"},{"id":"minecraft:dune_armor_trim_smithing_template","localizedName":"Dune Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.dune_armor_trim_smithing_template"},{"id":"minecraft:echo_shard","localizedName":"Echo Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.echo_shard"},{"id":"minecraft:egg","localizedName":"Egg","maxStackSize":16,"unlocalizedName":"item.minecraft.egg"},{"id":"minecraft:elder_guardian_spawn_egg","localizedName":"Elder Guardian Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.elder_guardian_spawn_egg"},{"id":"minecraft:elytra","localizedName":"Elytra","maxDamage":432,"maxStackSize":1,"unlocalizedName":"item.minecraft.elytra"},{"id":"minecraft:emerald","localizedName":"Emerald","maxStackSize":64,"unlocalizedName":"item.minecraft.emerald"},{"id":"minecraft:emerald_block","localizedName":"Block of Emerald","maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_block"},{"id":"minecraft:emerald_ore","localizedName":"Emerald Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.emerald_ore"},{"id":"minecraft:enchanted_book","localizedName":"Enchanted Book","maxStackSize":1,"unlocalizedName":"item.minecraft.enchanted_book"},{"id":"minecraft:enchanted_golden_apple","localizedName":"Enchanted Golden Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.enchanted_golden_apple"},{"id":"minecraft:enchanting_table","localizedName":"Enchanting Table","maxStackSize":64,"unlocalizedName":"block.minecraft.enchanting_table"},{"id":"minecraft:end_crystal","localizedName":"End Crystal","maxStackSize":64,"unlocalizedName":"item.minecraft.end_crystal"},{"id":"minecraft:end_portal_frame","localizedName":"End Portal Frame","maxStackSize":64,"unlocalizedName":"block.minecraft.end_portal_frame"},{"id":"minecraft:end_rod","localizedName":"End Rod","maxStackSize":64,"unlocalizedName":"block.minecraft.end_rod"},{"id":"minecraft:end_stone","localizedName":"End Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone"},{"id":"minecraft:end_stone_brick_slab","localizedName":"End Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_slab"},{"id":"minecraft:end_stone_brick_stairs","localizedName":"End Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_stairs"},{"id":"minecraft:end_stone_brick_wall","localizedName":"End Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_brick_wall"},{"id":"minecraft:end_stone_bricks","localizedName":"End Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.end_stone_bricks"},{"id":"minecraft:ender_chest","localizedName":"Ender Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.ender_chest"},{"id":"minecraft:ender_dragon_spawn_egg","localizedName":"Ender Dragon Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ender_dragon_spawn_egg"},{"id":"minecraft:ender_eye","localizedName":"Eye of Ender","maxStackSize":64,"unlocalizedName":"item.minecraft.ender_eye"},{"id":"minecraft:ender_pearl","localizedName":"Ender Pearl","maxStackSize":16,"unlocalizedName":"item.minecraft.ender_pearl"},{"id":"minecraft:enderman_spawn_egg","localizedName":"Enderman Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.enderman_spawn_egg"},{"id":"minecraft:endermite_spawn_egg","localizedName":"Endermite Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.endermite_spawn_egg"},{"id":"minecraft:evoker_spawn_egg","localizedName":"Evoker Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.evoker_spawn_egg"},{"id":"minecraft:experience_bottle","localizedName":"Bottle o\u0027 Enchanting","maxStackSize":64,"unlocalizedName":"item.minecraft.experience_bottle"},{"id":"minecraft:explorer_pottery_sherd","localizedName":"Explorer Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.explorer_pottery_sherd"},{"id":"minecraft:exposed_chiseled_copper","localizedName":"Exposed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_chiseled_copper"},{"id":"minecraft:exposed_copper","localizedName":"Exposed Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper"},{"id":"minecraft:exposed_copper_bulb","localizedName":"Exposed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_bulb"},{"id":"minecraft:exposed_copper_door","localizedName":"Exposed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_door"},{"id":"minecraft:exposed_copper_grate","localizedName":"Exposed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_grate"},{"id":"minecraft:exposed_copper_trapdoor","localizedName":"Exposed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_copper_trapdoor"},{"id":"minecraft:exposed_cut_copper","localizedName":"Exposed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper"},{"id":"minecraft:exposed_cut_copper_slab","localizedName":"Exposed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_slab"},{"id":"minecraft:exposed_cut_copper_stairs","localizedName":"Exposed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.exposed_cut_copper_stairs"},{"id":"minecraft:eye_armor_trim_smithing_template","localizedName":"Eye Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.eye_armor_trim_smithing_template"},{"id":"minecraft:farmland","localizedName":"Farmland","maxStackSize":64,"unlocalizedName":"block.minecraft.farmland"},{"id":"minecraft:feather","localizedName":"Feather","maxStackSize":64,"unlocalizedName":"item.minecraft.feather"},{"id":"minecraft:fermented_spider_eye","localizedName":"Fermented Spider Eye","maxStackSize":64,"unlocalizedName":"item.minecraft.fermented_spider_eye"},{"id":"minecraft:fern","localizedName":"Fern","maxStackSize":64,"unlocalizedName":"block.minecraft.fern"},{"id":"minecraft:field_masoned_banner_pattern","localizedName":"Field Masoned Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.field_masoned_banner_pattern"},{"id":"minecraft:filled_map","localizedName":"Map","maxStackSize":64,"unlocalizedName":"item.minecraft.filled_map"},{"id":"minecraft:fire_charge","localizedName":"Fire Charge","maxStackSize":64,"unlocalizedName":"item.minecraft.fire_charge"},{"id":"minecraft:fire_coral","localizedName":"Fire Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral"},{"id":"minecraft:fire_coral_block","localizedName":"Fire Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_block"},{"id":"minecraft:fire_coral_fan","localizedName":"Fire Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.fire_coral_fan"},{"id":"minecraft:firework_rocket","localizedName":"Firework Rocket","maxStackSize":64,"unlocalizedName":"item.minecraft.firework_rocket"},{"id":"minecraft:firework_star","localizedName":"Firework Star","maxStackSize":64,"unlocalizedName":"item.minecraft.firework_star"},{"id":"minecraft:fishing_rod","localizedName":"Fishing Rod","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.fishing_rod"},{"id":"minecraft:fletching_table","localizedName":"Fletching Table","maxStackSize":64,"unlocalizedName":"block.minecraft.fletching_table"},{"id":"minecraft:flint","localizedName":"Flint","maxStackSize":64,"unlocalizedName":"item.minecraft.flint"},{"id":"minecraft:flint_and_steel","localizedName":"Flint and Steel","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.flint_and_steel"},{"id":"minecraft:flow_armor_trim_smithing_template","localizedName":"Flow Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.flow_armor_trim_smithing_template"},{"id":"minecraft:flow_banner_pattern","localizedName":"Flow Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.flow_banner_pattern"},{"id":"minecraft:flow_pottery_sherd","localizedName":"Flow Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.flow_pottery_sherd"},{"id":"minecraft:flower_banner_pattern","localizedName":"Flower Charge Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.flower_banner_pattern"},{"id":"minecraft:flower_pot","localizedName":"Flower Pot","maxStackSize":64,"unlocalizedName":"block.minecraft.flower_pot"},{"id":"minecraft:flowering_azalea","localizedName":"Flowering Azalea","maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea"},{"id":"minecraft:flowering_azalea_leaves","localizedName":"Flowering Azalea Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.flowering_azalea_leaves"},{"id":"minecraft:fox_spawn_egg","localizedName":"Fox Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.fox_spawn_egg"},{"id":"minecraft:friend_pottery_sherd","localizedName":"Friend Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.friend_pottery_sherd"},{"id":"minecraft:frog_spawn_egg","localizedName":"Frog Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.frog_spawn_egg"},{"id":"minecraft:frogspawn","localizedName":"Frogspawn","maxStackSize":64,"unlocalizedName":"block.minecraft.frogspawn"},{"id":"minecraft:furnace","localizedName":"Furnace","maxStackSize":64,"unlocalizedName":"block.minecraft.furnace"},{"id":"minecraft:furnace_minecart","localizedName":"Minecart with Furnace","maxStackSize":1,"unlocalizedName":"item.minecraft.furnace_minecart"},{"id":"minecraft:ghast_spawn_egg","localizedName":"Ghast Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_spawn_egg"},{"id":"minecraft:ghast_tear","localizedName":"Ghast Tear","maxStackSize":64,"unlocalizedName":"item.minecraft.ghast_tear"},{"id":"minecraft:gilded_blackstone","localizedName":"Gilded Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.gilded_blackstone"},{"id":"minecraft:glass","localizedName":"Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.glass"},{"id":"minecraft:glass_bottle","localizedName":"Glass Bottle","maxStackSize":64,"unlocalizedName":"item.minecraft.glass_bottle"},{"id":"minecraft:glass_pane","localizedName":"Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.glass_pane"},{"id":"minecraft:glistering_melon_slice","localizedName":"Glistering Melon Slice","maxStackSize":64,"unlocalizedName":"item.minecraft.glistering_melon_slice"},{"id":"minecraft:globe_banner_pattern","localizedName":"Globe Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.globe_banner_pattern"},{"id":"minecraft:glow_berries","localizedName":"Glow Berries","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_berries"},{"id":"minecraft:glow_ink_sac","localizedName":"Glow Ink Sac","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_ink_sac"},{"id":"minecraft:glow_item_frame","localizedName":"Glow Item Frame","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_item_frame"},{"id":"minecraft:glow_lichen","localizedName":"Glow Lichen","maxStackSize":64,"unlocalizedName":"block.minecraft.glow_lichen"},{"id":"minecraft:glow_squid_spawn_egg","localizedName":"Glow Squid Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.glow_squid_spawn_egg"},{"id":"minecraft:glowstone","localizedName":"Glowstone","maxStackSize":64,"unlocalizedName":"block.minecraft.glowstone"},{"id":"minecraft:glowstone_dust","localizedName":"Glowstone Dust","maxStackSize":64,"unlocalizedName":"item.minecraft.glowstone_dust"},{"id":"minecraft:goat_horn","localizedName":"Goat Horn","maxStackSize":1,"unlocalizedName":"item.minecraft.goat_horn"},{"id":"minecraft:goat_spawn_egg","localizedName":"Goat Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.goat_spawn_egg"},{"id":"minecraft:gold_block","localizedName":"Block of Gold","maxStackSize":64,"unlocalizedName":"block.minecraft.gold_block"},{"id":"minecraft:gold_ingot","localizedName":"Gold Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.gold_ingot"},{"id":"minecraft:gold_nugget","localizedName":"Gold Nugget","maxStackSize":64,"unlocalizedName":"item.minecraft.gold_nugget"},{"id":"minecraft:gold_ore","localizedName":"Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.gold_ore"},{"id":"minecraft:golden_apple","localizedName":"Golden Apple","maxStackSize":64,"unlocalizedName":"item.minecraft.golden_apple"},{"id":"minecraft:golden_axe","localizedName":"Golden Axe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_axe"},{"id":"minecraft:golden_boots","localizedName":"Golden Boots","maxDamage":91,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_boots"},{"id":"minecraft:golden_carrot","localizedName":"Golden Carrot","maxStackSize":64,"unlocalizedName":"item.minecraft.golden_carrot"},{"id":"minecraft:golden_chestplate","localizedName":"Golden Chestplate","maxDamage":112,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_chestplate"},{"id":"minecraft:golden_helmet","localizedName":"Golden Helmet","maxDamage":77,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_helmet"},{"id":"minecraft:golden_hoe","localizedName":"Golden Hoe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_hoe"},{"id":"minecraft:golden_horse_armor","localizedName":"Golden Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.golden_horse_armor"},{"id":"minecraft:golden_leggings","localizedName":"Golden Leggings","maxDamage":105,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_leggings"},{"id":"minecraft:golden_pickaxe","localizedName":"Golden Pickaxe","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_pickaxe"},{"id":"minecraft:golden_shovel","localizedName":"Golden Shovel","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_shovel"},{"id":"minecraft:golden_sword","localizedName":"Golden Sword","maxDamage":32,"maxStackSize":1,"unlocalizedName":"item.minecraft.golden_sword"},{"id":"minecraft:granite","localizedName":"Granite","maxStackSize":64,"unlocalizedName":"block.minecraft.granite"},{"id":"minecraft:granite_slab","localizedName":"Granite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_slab"},{"id":"minecraft:granite_stairs","localizedName":"Granite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_stairs"},{"id":"minecraft:granite_wall","localizedName":"Granite Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.granite_wall"},{"id":"minecraft:grass_block","localizedName":"Grass Block","maxStackSize":64,"unlocalizedName":"block.minecraft.grass_block"},{"id":"minecraft:gravel","localizedName":"Gravel","maxStackSize":64,"unlocalizedName":"block.minecraft.gravel"},{"id":"minecraft:gray_banner","localizedName":"Gray Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.gray_banner"},{"id":"minecraft:gray_bed","localizedName":"Gray Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.gray_bed"},{"id":"minecraft:gray_bundle","localizedName":"Gray Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.gray_bundle"},{"id":"minecraft:gray_candle","localizedName":"Gray Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_candle"},{"id":"minecraft:gray_carpet","localizedName":"Gray Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_carpet"},{"id":"minecraft:gray_concrete","localizedName":"Gray Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete"},{"id":"minecraft:gray_concrete_powder","localizedName":"Gray Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_concrete_powder"},{"id":"minecraft:gray_dye","localizedName":"Gray Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.gray_dye"},{"id":"minecraft:gray_glazed_terracotta","localizedName":"Gray Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_glazed_terracotta"},{"id":"minecraft:gray_shulker_box","localizedName":"Gray Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.gray_shulker_box"},{"id":"minecraft:gray_stained_glass","localizedName":"Gray Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass"},{"id":"minecraft:gray_stained_glass_pane","localizedName":"Gray Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_stained_glass_pane"},{"id":"minecraft:gray_terracotta","localizedName":"Gray Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_terracotta"},{"id":"minecraft:gray_wool","localizedName":"Gray Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.gray_wool"},{"id":"minecraft:green_banner","localizedName":"Green Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.green_banner"},{"id":"minecraft:green_bed","localizedName":"Green Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.green_bed"},{"id":"minecraft:green_bundle","localizedName":"Green Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.green_bundle"},{"id":"minecraft:green_candle","localizedName":"Green Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.green_candle"},{"id":"minecraft:green_carpet","localizedName":"Green Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.green_carpet"},{"id":"minecraft:green_concrete","localizedName":"Green Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete"},{"id":"minecraft:green_concrete_powder","localizedName":"Green Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.green_concrete_powder"},{"id":"minecraft:green_dye","localizedName":"Green Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.green_dye"},{"id":"minecraft:green_glazed_terracotta","localizedName":"Green Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.green_glazed_terracotta"},{"id":"minecraft:green_shulker_box","localizedName":"Green Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.green_shulker_box"},{"id":"minecraft:green_stained_glass","localizedName":"Green Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass"},{"id":"minecraft:green_stained_glass_pane","localizedName":"Green Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.green_stained_glass_pane"},{"id":"minecraft:green_terracotta","localizedName":"Green Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.green_terracotta"},{"id":"minecraft:green_wool","localizedName":"Green Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.green_wool"},{"id":"minecraft:grindstone","localizedName":"Grindstone","maxStackSize":64,"unlocalizedName":"block.minecraft.grindstone"},{"id":"minecraft:guardian_spawn_egg","localizedName":"Guardian Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.guardian_spawn_egg"},{"id":"minecraft:gunpowder","localizedName":"Gunpowder","maxStackSize":64,"unlocalizedName":"item.minecraft.gunpowder"},{"id":"minecraft:guster_banner_pattern","localizedName":"Guster Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.guster_banner_pattern"},{"id":"minecraft:guster_pottery_sherd","localizedName":"Guster Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.guster_pottery_sherd"},{"id":"minecraft:hanging_roots","localizedName":"Hanging Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.hanging_roots"},{"id":"minecraft:hay_block","localizedName":"Hay Bale","maxStackSize":64,"unlocalizedName":"block.minecraft.hay_block"},{"id":"minecraft:heart_of_the_sea","localizedName":"Heart of the Sea","maxStackSize":64,"unlocalizedName":"item.minecraft.heart_of_the_sea"},{"id":"minecraft:heart_pottery_sherd","localizedName":"Heart Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.heart_pottery_sherd"},{"id":"minecraft:heartbreak_pottery_sherd","localizedName":"Heartbreak Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.heartbreak_pottery_sherd"},{"id":"minecraft:heavy_core","localizedName":"Heavy Core","maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_core"},{"id":"minecraft:heavy_weighted_pressure_plate","localizedName":"Heavy Weighted Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.heavy_weighted_pressure_plate"},{"id":"minecraft:hoglin_spawn_egg","localizedName":"Hoglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.hoglin_spawn_egg"},{"id":"minecraft:honey_block","localizedName":"Honey Block","maxStackSize":64,"unlocalizedName":"block.minecraft.honey_block"},{"id":"minecraft:honey_bottle","localizedName":"Honey Bottle","maxStackSize":16,"unlocalizedName":"item.minecraft.honey_bottle"},{"id":"minecraft:honeycomb","localizedName":"Honeycomb","maxStackSize":64,"unlocalizedName":"item.minecraft.honeycomb"},{"id":"minecraft:honeycomb_block","localizedName":"Honeycomb Block","maxStackSize":64,"unlocalizedName":"block.minecraft.honeycomb_block"},{"id":"minecraft:hopper","localizedName":"Hopper","maxStackSize":64,"unlocalizedName":"block.minecraft.hopper"},{"id":"minecraft:hopper_minecart","localizedName":"Minecart with Hopper","maxStackSize":1,"unlocalizedName":"item.minecraft.hopper_minecart"},{"id":"minecraft:horn_coral","localizedName":"Horn Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral"},{"id":"minecraft:horn_coral_block","localizedName":"Horn Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_block"},{"id":"minecraft:horn_coral_fan","localizedName":"Horn Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.horn_coral_fan"},{"id":"minecraft:horse_spawn_egg","localizedName":"Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.horse_spawn_egg"},{"id":"minecraft:host_armor_trim_smithing_template","localizedName":"Host Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.host_armor_trim_smithing_template"},{"id":"minecraft:howl_pottery_sherd","localizedName":"Howl Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.howl_pottery_sherd"},{"id":"minecraft:husk_spawn_egg","localizedName":"Husk Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.husk_spawn_egg"},{"id":"minecraft:ice","localizedName":"Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.ice"},{"id":"minecraft:infested_chiseled_stone_bricks","localizedName":"Infested Chiseled Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_chiseled_stone_bricks"},{"id":"minecraft:infested_cobblestone","localizedName":"Infested Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cobblestone"},{"id":"minecraft:infested_cracked_stone_bricks","localizedName":"Infested Cracked Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_cracked_stone_bricks"},{"id":"minecraft:infested_deepslate","localizedName":"Infested Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_deepslate"},{"id":"minecraft:infested_mossy_stone_bricks","localizedName":"Infested Mossy Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_mossy_stone_bricks"},{"id":"minecraft:infested_stone","localizedName":"Infested Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone"},{"id":"minecraft:infested_stone_bricks","localizedName":"Infested Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.infested_stone_bricks"},{"id":"minecraft:ink_sac","localizedName":"Ink Sac","maxStackSize":64,"unlocalizedName":"item.minecraft.ink_sac"},{"id":"minecraft:iron_axe","localizedName":"Iron Axe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_axe"},{"id":"minecraft:iron_bars","localizedName":"Iron Bars","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_bars"},{"id":"minecraft:iron_block","localizedName":"Block of Iron","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_block"},{"id":"minecraft:iron_boots","localizedName":"Iron Boots","maxDamage":195,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_boots"},{"id":"minecraft:iron_chestplate","localizedName":"Iron Chestplate","maxDamage":240,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_chestplate"},{"id":"minecraft:iron_door","localizedName":"Iron Door","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_door"},{"id":"minecraft:iron_golem_spawn_egg","localizedName":"Iron Golem Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_golem_spawn_egg"},{"id":"minecraft:iron_helmet","localizedName":"Iron Helmet","maxDamage":165,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_helmet"},{"id":"minecraft:iron_hoe","localizedName":"Iron Hoe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_hoe"},{"id":"minecraft:iron_horse_armor","localizedName":"Iron Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.iron_horse_armor"},{"id":"minecraft:iron_ingot","localizedName":"Iron Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_ingot"},{"id":"minecraft:iron_leggings","localizedName":"Iron Leggings","maxDamage":225,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_leggings"},{"id":"minecraft:iron_nugget","localizedName":"Iron Nugget","maxStackSize":64,"unlocalizedName":"item.minecraft.iron_nugget"},{"id":"minecraft:iron_ore","localizedName":"Iron Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_ore"},{"id":"minecraft:iron_pickaxe","localizedName":"Iron Pickaxe","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_pickaxe"},{"id":"minecraft:iron_shovel","localizedName":"Iron Shovel","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_shovel"},{"id":"minecraft:iron_sword","localizedName":"Iron Sword","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.iron_sword"},{"id":"minecraft:iron_trapdoor","localizedName":"Iron Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.iron_trapdoor"},{"id":"minecraft:item_frame","localizedName":"Item Frame","maxStackSize":64,"unlocalizedName":"item.minecraft.item_frame"},{"id":"minecraft:jack_o_lantern","localizedName":"Jack o\u0027Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.jack_o_lantern"},{"id":"minecraft:jigsaw","localizedName":"Jigsaw Block","maxStackSize":64,"unlocalizedName":"block.minecraft.jigsaw"},{"id":"minecraft:jukebox","localizedName":"Jukebox","maxStackSize":64,"unlocalizedName":"block.minecraft.jukebox"},{"id":"minecraft:jungle_boat","localizedName":"Jungle Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_boat"},{"id":"minecraft:jungle_button","localizedName":"Jungle Button","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_button"},{"id":"minecraft:jungle_chest_boat","localizedName":"Jungle Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.jungle_chest_boat"},{"id":"minecraft:jungle_door","localizedName":"Jungle Door","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_door"},{"id":"minecraft:jungle_fence","localizedName":"Jungle Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence"},{"id":"minecraft:jungle_fence_gate","localizedName":"Jungle Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_fence_gate"},{"id":"minecraft:jungle_hanging_sign","localizedName":"Jungle Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_hanging_sign"},{"id":"minecraft:jungle_leaves","localizedName":"Jungle Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_leaves"},{"id":"minecraft:jungle_log","localizedName":"Jungle Log","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_log"},{"id":"minecraft:jungle_planks","localizedName":"Jungle Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_planks"},{"id":"minecraft:jungle_pressure_plate","localizedName":"Jungle Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_pressure_plate"},{"id":"minecraft:jungle_sapling","localizedName":"Jungle Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_sapling"},{"id":"minecraft:jungle_sign","localizedName":"Jungle Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.jungle_sign"},{"id":"minecraft:jungle_slab","localizedName":"Jungle Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_slab"},{"id":"minecraft:jungle_stairs","localizedName":"Jungle Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_stairs"},{"id":"minecraft:jungle_trapdoor","localizedName":"Jungle Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_trapdoor"},{"id":"minecraft:jungle_wood","localizedName":"Jungle Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.jungle_wood"},{"id":"minecraft:kelp","localizedName":"Kelp","maxStackSize":64,"unlocalizedName":"block.minecraft.kelp"},{"id":"minecraft:knowledge_book","localizedName":"Knowledge Book","maxStackSize":1,"unlocalizedName":"item.minecraft.knowledge_book"},{"id":"minecraft:ladder","localizedName":"Ladder","maxStackSize":64,"unlocalizedName":"block.minecraft.ladder"},{"id":"minecraft:lantern","localizedName":"Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.lantern"},{"id":"minecraft:lapis_block","localizedName":"Block of Lapis Lazuli","maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_block"},{"id":"minecraft:lapis_lazuli","localizedName":"Lapis Lazuli","maxStackSize":64,"unlocalizedName":"item.minecraft.lapis_lazuli"},{"id":"minecraft:lapis_ore","localizedName":"Lapis Lazuli Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.lapis_ore"},{"id":"minecraft:large_amethyst_bud","localizedName":"Large Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.large_amethyst_bud"},{"id":"minecraft:large_fern","localizedName":"Large Fern","maxStackSize":64,"unlocalizedName":"block.minecraft.large_fern"},{"id":"minecraft:lava_bucket","localizedName":"Lava Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.lava_bucket"},{"id":"minecraft:lead","localizedName":"Lead","maxStackSize":64,"unlocalizedName":"item.minecraft.lead"},{"id":"minecraft:leather","localizedName":"Leather","maxStackSize":64,"unlocalizedName":"item.minecraft.leather"},{"id":"minecraft:leather_boots","localizedName":"Leather Boots","maxDamage":65,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_boots"},{"id":"minecraft:leather_chestplate","localizedName":"Leather Tunic","maxDamage":80,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_chestplate"},{"id":"minecraft:leather_helmet","localizedName":"Leather Cap","maxDamage":55,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_helmet"},{"id":"minecraft:leather_horse_armor","localizedName":"Leather Horse Armor","maxStackSize":1,"unlocalizedName":"item.minecraft.leather_horse_armor"},{"id":"minecraft:leather_leggings","localizedName":"Leather Pants","maxDamage":75,"maxStackSize":1,"unlocalizedName":"item.minecraft.leather_leggings"},{"id":"minecraft:lectern","localizedName":"Lectern","maxStackSize":64,"unlocalizedName":"block.minecraft.lectern"},{"id":"minecraft:lever","localizedName":"Lever","maxStackSize":64,"unlocalizedName":"block.minecraft.lever"},{"id":"minecraft:light","localizedName":"Light","maxStackSize":64,"unlocalizedName":"block.minecraft.light"},{"id":"minecraft:light_blue_banner","localizedName":"Light Blue Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.light_blue_banner"},{"id":"minecraft:light_blue_bed","localizedName":"Light Blue Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_bed"},{"id":"minecraft:light_blue_bundle","localizedName":"Light Blue Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.light_blue_bundle"},{"id":"minecraft:light_blue_candle","localizedName":"Light Blue Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_candle"},{"id":"minecraft:light_blue_carpet","localizedName":"Light Blue Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_carpet"},{"id":"minecraft:light_blue_concrete","localizedName":"Light Blue Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete"},{"id":"minecraft:light_blue_concrete_powder","localizedName":"Light Blue Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_concrete_powder"},{"id":"minecraft:light_blue_dye","localizedName":"Light Blue Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.light_blue_dye"},{"id":"minecraft:light_blue_glazed_terracotta","localizedName":"Light Blue Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_glazed_terracotta"},{"id":"minecraft:light_blue_shulker_box","localizedName":"Light Blue Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.light_blue_shulker_box"},{"id":"minecraft:light_blue_stained_glass","localizedName":"Light Blue Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass"},{"id":"minecraft:light_blue_stained_glass_pane","localizedName":"Light Blue Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_stained_glass_pane"},{"id":"minecraft:light_blue_terracotta","localizedName":"Light Blue Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_terracotta"},{"id":"minecraft:light_blue_wool","localizedName":"Light Blue Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.light_blue_wool"},{"id":"minecraft:light_gray_banner","localizedName":"Light Gray Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.light_gray_banner"},{"id":"minecraft:light_gray_bed","localizedName":"Light Gray Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_bed"},{"id":"minecraft:light_gray_bundle","localizedName":"Light Gray Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.light_gray_bundle"},{"id":"minecraft:light_gray_candle","localizedName":"Light Gray Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_candle"},{"id":"minecraft:light_gray_carpet","localizedName":"Light Gray Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_carpet"},{"id":"minecraft:light_gray_concrete","localizedName":"Light Gray Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete"},{"id":"minecraft:light_gray_concrete_powder","localizedName":"Light Gray Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_concrete_powder"},{"id":"minecraft:light_gray_dye","localizedName":"Light Gray Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.light_gray_dye"},{"id":"minecraft:light_gray_glazed_terracotta","localizedName":"Light Gray Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_glazed_terracotta"},{"id":"minecraft:light_gray_shulker_box","localizedName":"Light Gray Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.light_gray_shulker_box"},{"id":"minecraft:light_gray_stained_glass","localizedName":"Light Gray Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass"},{"id":"minecraft:light_gray_stained_glass_pane","localizedName":"Light Gray Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_stained_glass_pane"},{"id":"minecraft:light_gray_terracotta","localizedName":"Light Gray Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_terracotta"},{"id":"minecraft:light_gray_wool","localizedName":"Light Gray Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.light_gray_wool"},{"id":"minecraft:light_weighted_pressure_plate","localizedName":"Light Weighted Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.light_weighted_pressure_plate"},{"id":"minecraft:lightning_rod","localizedName":"Lightning Rod","maxStackSize":64,"unlocalizedName":"block.minecraft.lightning_rod"},{"id":"minecraft:lilac","localizedName":"Lilac","maxStackSize":64,"unlocalizedName":"block.minecraft.lilac"},{"id":"minecraft:lily_of_the_valley","localizedName":"Lily of the Valley","maxStackSize":64,"unlocalizedName":"block.minecraft.lily_of_the_valley"},{"id":"minecraft:lily_pad","localizedName":"Lily Pad","maxStackSize":64,"unlocalizedName":"block.minecraft.lily_pad"},{"id":"minecraft:lime_banner","localizedName":"Lime Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.lime_banner"},{"id":"minecraft:lime_bed","localizedName":"Lime Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.lime_bed"},{"id":"minecraft:lime_bundle","localizedName":"Lime Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.lime_bundle"},{"id":"minecraft:lime_candle","localizedName":"Lime Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_candle"},{"id":"minecraft:lime_carpet","localizedName":"Lime Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_carpet"},{"id":"minecraft:lime_concrete","localizedName":"Lime Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete"},{"id":"minecraft:lime_concrete_powder","localizedName":"Lime Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_concrete_powder"},{"id":"minecraft:lime_dye","localizedName":"Lime Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.lime_dye"},{"id":"minecraft:lime_glazed_terracotta","localizedName":"Lime Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_glazed_terracotta"},{"id":"minecraft:lime_shulker_box","localizedName":"Lime Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.lime_shulker_box"},{"id":"minecraft:lime_stained_glass","localizedName":"Lime Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass"},{"id":"minecraft:lime_stained_glass_pane","localizedName":"Lime Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_stained_glass_pane"},{"id":"minecraft:lime_terracotta","localizedName":"Lime Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_terracotta"},{"id":"minecraft:lime_wool","localizedName":"Lime Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.lime_wool"},{"id":"minecraft:lingering_potion","localizedName":"Lingering Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.lingering_potion"},{"id":"minecraft:llama_spawn_egg","localizedName":"Llama Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.llama_spawn_egg"},{"id":"minecraft:lodestone","localizedName":"Lodestone","maxStackSize":64,"unlocalizedName":"block.minecraft.lodestone"},{"id":"minecraft:loom","localizedName":"Loom","maxStackSize":64,"unlocalizedName":"block.minecraft.loom"},{"id":"minecraft:mace","localizedName":"Mace","maxDamage":500,"maxStackSize":1,"unlocalizedName":"item.minecraft.mace"},{"id":"minecraft:magenta_banner","localizedName":"Magenta Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.magenta_banner"},{"id":"minecraft:magenta_bed","localizedName":"Magenta Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_bed"},{"id":"minecraft:magenta_bundle","localizedName":"Magenta Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.magenta_bundle"},{"id":"minecraft:magenta_candle","localizedName":"Magenta Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_candle"},{"id":"minecraft:magenta_carpet","localizedName":"Magenta Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_carpet"},{"id":"minecraft:magenta_concrete","localizedName":"Magenta Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete"},{"id":"minecraft:magenta_concrete_powder","localizedName":"Magenta Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_concrete_powder"},{"id":"minecraft:magenta_dye","localizedName":"Magenta Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.magenta_dye"},{"id":"minecraft:magenta_glazed_terracotta","localizedName":"Magenta Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_glazed_terracotta"},{"id":"minecraft:magenta_shulker_box","localizedName":"Magenta Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.magenta_shulker_box"},{"id":"minecraft:magenta_stained_glass","localizedName":"Magenta Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass"},{"id":"minecraft:magenta_stained_glass_pane","localizedName":"Magenta Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_stained_glass_pane"},{"id":"minecraft:magenta_terracotta","localizedName":"Magenta Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_terracotta"},{"id":"minecraft:magenta_wool","localizedName":"Magenta Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.magenta_wool"},{"id":"minecraft:magma_block","localizedName":"Magma Block","maxStackSize":64,"unlocalizedName":"block.minecraft.magma_block"},{"id":"minecraft:magma_cream","localizedName":"Magma Cream","maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cream"},{"id":"minecraft:magma_cube_spawn_egg","localizedName":"Magma Cube Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.magma_cube_spawn_egg"},{"id":"minecraft:mangrove_boat","localizedName":"Mangrove Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_boat"},{"id":"minecraft:mangrove_button","localizedName":"Mangrove Button","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_button"},{"id":"minecraft:mangrove_chest_boat","localizedName":"Mangrove Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.mangrove_chest_boat"},{"id":"minecraft:mangrove_door","localizedName":"Mangrove Door","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_door"},{"id":"minecraft:mangrove_fence","localizedName":"Mangrove Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence"},{"id":"minecraft:mangrove_fence_gate","localizedName":"Mangrove Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_fence_gate"},{"id":"minecraft:mangrove_hanging_sign","localizedName":"Mangrove Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.mangrove_hanging_sign"},{"id":"minecraft:mangrove_leaves","localizedName":"Mangrove Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_leaves"},{"id":"minecraft:mangrove_log","localizedName":"Mangrove Log","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_log"},{"id":"minecraft:mangrove_planks","localizedName":"Mangrove Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_planks"},{"id":"minecraft:mangrove_pressure_plate","localizedName":"Mangrove Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_pressure_plate"},{"id":"minecraft:mangrove_propagule","localizedName":"Mangrove Propagule","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_propagule"},{"id":"minecraft:mangrove_roots","localizedName":"Mangrove Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_roots"},{"id":"minecraft:mangrove_sign","localizedName":"Mangrove Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.mangrove_sign"},{"id":"minecraft:mangrove_slab","localizedName":"Mangrove Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_slab"},{"id":"minecraft:mangrove_stairs","localizedName":"Mangrove Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_stairs"},{"id":"minecraft:mangrove_trapdoor","localizedName":"Mangrove Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_trapdoor"},{"id":"minecraft:mangrove_wood","localizedName":"Mangrove Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.mangrove_wood"},{"id":"minecraft:map","localizedName":"Empty Map","maxStackSize":64,"unlocalizedName":"item.minecraft.map"},{"id":"minecraft:medium_amethyst_bud","localizedName":"Medium Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.medium_amethyst_bud"},{"id":"minecraft:melon","localizedName":"Melon","maxStackSize":64,"unlocalizedName":"block.minecraft.melon"},{"id":"minecraft:melon_seeds","localizedName":"Melon Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.melon_seeds"},{"id":"minecraft:melon_slice","localizedName":"Melon Slice","maxStackSize":64,"unlocalizedName":"item.minecraft.melon_slice"},{"id":"minecraft:milk_bucket","localizedName":"Milk Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.milk_bucket"},{"id":"minecraft:minecart","localizedName":"Minecart","maxStackSize":1,"unlocalizedName":"item.minecraft.minecart"},{"id":"minecraft:miner_pottery_sherd","localizedName":"Miner Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.miner_pottery_sherd"},{"id":"minecraft:mojang_banner_pattern","localizedName":"Thing Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.mojang_banner_pattern"},{"id":"minecraft:mooshroom_spawn_egg","localizedName":"Mooshroom Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.mooshroom_spawn_egg"},{"id":"minecraft:moss_block","localizedName":"Moss Block","maxStackSize":64,"unlocalizedName":"block.minecraft.moss_block"},{"id":"minecraft:moss_carpet","localizedName":"Moss Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.moss_carpet"},{"id":"minecraft:mossy_cobblestone","localizedName":"Mossy Cobblestone","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone"},{"id":"minecraft:mossy_cobblestone_slab","localizedName":"Mossy Cobblestone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_slab"},{"id":"minecraft:mossy_cobblestone_stairs","localizedName":"Mossy Cobblestone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_stairs"},{"id":"minecraft:mossy_cobblestone_wall","localizedName":"Mossy Cobblestone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_cobblestone_wall"},{"id":"minecraft:mossy_stone_brick_slab","localizedName":"Mossy Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_slab"},{"id":"minecraft:mossy_stone_brick_stairs","localizedName":"Mossy Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_stairs"},{"id":"minecraft:mossy_stone_brick_wall","localizedName":"Mossy Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_brick_wall"},{"id":"minecraft:mossy_stone_bricks","localizedName":"Mossy Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.mossy_stone_bricks"},{"id":"minecraft:mourner_pottery_sherd","localizedName":"Mourner Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.mourner_pottery_sherd"},{"id":"minecraft:mud","localizedName":"Mud","maxStackSize":64,"unlocalizedName":"block.minecraft.mud"},{"id":"minecraft:mud_brick_slab","localizedName":"Mud Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_slab"},{"id":"minecraft:mud_brick_stairs","localizedName":"Mud Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_stairs"},{"id":"minecraft:mud_brick_wall","localizedName":"Mud Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_brick_wall"},{"id":"minecraft:mud_bricks","localizedName":"Mud Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.mud_bricks"},{"id":"minecraft:muddy_mangrove_roots","localizedName":"Muddy Mangrove Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.muddy_mangrove_roots"},{"id":"minecraft:mule_spawn_egg","localizedName":"Mule Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.mule_spawn_egg"},{"id":"minecraft:mushroom_stem","localizedName":"Mushroom Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.mushroom_stem"},{"id":"minecraft:mushroom_stew","localizedName":"Mushroom Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.mushroom_stew"},{"id":"minecraft:music_disc_11","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_11"},{"id":"minecraft:music_disc_13","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_13"},{"id":"minecraft:music_disc_5","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_5"},{"id":"minecraft:music_disc_blocks","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_blocks"},{"id":"minecraft:music_disc_cat","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_cat"},{"id":"minecraft:music_disc_chirp","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_chirp"},{"id":"minecraft:music_disc_creator","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_creator"},{"id":"minecraft:music_disc_creator_music_box","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_creator_music_box"},{"id":"minecraft:music_disc_far","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_far"},{"id":"minecraft:music_disc_mall","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mall"},{"id":"minecraft:music_disc_mellohi","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_mellohi"},{"id":"minecraft:music_disc_otherside","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_otherside"},{"id":"minecraft:music_disc_pigstep","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_pigstep"},{"id":"minecraft:music_disc_precipice","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_precipice"},{"id":"minecraft:music_disc_relic","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_relic"},{"id":"minecraft:music_disc_stal","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_stal"},{"id":"minecraft:music_disc_strad","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_strad"},{"id":"minecraft:music_disc_wait","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_wait"},{"id":"minecraft:music_disc_ward","localizedName":"Music Disc","maxStackSize":1,"unlocalizedName":"item.minecraft.music_disc_ward"},{"id":"minecraft:mutton","localizedName":"Raw Mutton","maxStackSize":64,"unlocalizedName":"item.minecraft.mutton"},{"id":"minecraft:mycelium","localizedName":"Mycelium","maxStackSize":64,"unlocalizedName":"block.minecraft.mycelium"},{"id":"minecraft:name_tag","localizedName":"Name Tag","maxStackSize":64,"unlocalizedName":"item.minecraft.name_tag"},{"id":"minecraft:nautilus_shell","localizedName":"Nautilus Shell","maxStackSize":64,"unlocalizedName":"item.minecraft.nautilus_shell"},{"id":"minecraft:nether_brick","localizedName":"Nether Brick","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_brick"},{"id":"minecraft:nether_brick_fence","localizedName":"Nether Brick Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_fence"},{"id":"minecraft:nether_brick_slab","localizedName":"Nether Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_slab"},{"id":"minecraft:nether_brick_stairs","localizedName":"Nether Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_stairs"},{"id":"minecraft:nether_brick_wall","localizedName":"Nether Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_brick_wall"},{"id":"minecraft:nether_bricks","localizedName":"Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_bricks"},{"id":"minecraft:nether_gold_ore","localizedName":"Nether Gold Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_gold_ore"},{"id":"minecraft:nether_quartz_ore","localizedName":"Nether Quartz Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_quartz_ore"},{"id":"minecraft:nether_sprouts","localizedName":"Nether Sprouts","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_sprouts"},{"id":"minecraft:nether_star","localizedName":"Nether Star","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_star"},{"id":"minecraft:nether_wart","localizedName":"Nether Wart","maxStackSize":64,"unlocalizedName":"item.minecraft.nether_wart"},{"id":"minecraft:nether_wart_block","localizedName":"Nether Wart Block","maxStackSize":64,"unlocalizedName":"block.minecraft.nether_wart_block"},{"id":"minecraft:netherite_axe","localizedName":"Netherite Axe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_axe"},{"id":"minecraft:netherite_block","localizedName":"Block of Netherite","maxStackSize":64,"unlocalizedName":"block.minecraft.netherite_block"},{"id":"minecraft:netherite_boots","localizedName":"Netherite Boots","maxDamage":481,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_boots"},{"id":"minecraft:netherite_chestplate","localizedName":"Netherite Chestplate","maxDamage":592,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_chestplate"},{"id":"minecraft:netherite_helmet","localizedName":"Netherite Helmet","maxDamage":407,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_helmet"},{"id":"minecraft:netherite_hoe","localizedName":"Netherite Hoe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_hoe"},{"id":"minecraft:netherite_ingot","localizedName":"Netherite Ingot","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_ingot"},{"id":"minecraft:netherite_leggings","localizedName":"Netherite Leggings","maxDamage":555,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_leggings"},{"id":"minecraft:netherite_pickaxe","localizedName":"Netherite Pickaxe","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_pickaxe"},{"id":"minecraft:netherite_scrap","localizedName":"Netherite Scrap","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_scrap"},{"id":"minecraft:netherite_shovel","localizedName":"Netherite Shovel","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_shovel"},{"id":"minecraft:netherite_sword","localizedName":"Netherite Sword","maxDamage":2031,"maxStackSize":1,"unlocalizedName":"item.minecraft.netherite_sword"},{"id":"minecraft:netherite_upgrade_smithing_template","localizedName":"Netherite Upgrade","maxStackSize":64,"unlocalizedName":"item.minecraft.netherite_upgrade_smithing_template"},{"id":"minecraft:netherrack","localizedName":"Netherrack","maxStackSize":64,"unlocalizedName":"block.minecraft.netherrack"},{"id":"minecraft:note_block","localizedName":"Note Block","maxStackSize":64,"unlocalizedName":"block.minecraft.note_block"},{"id":"minecraft:oak_boat","localizedName":"Oak Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.oak_boat"},{"id":"minecraft:oak_button","localizedName":"Oak Button","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_button"},{"id":"minecraft:oak_chest_boat","localizedName":"Oak Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.oak_chest_boat"},{"id":"minecraft:oak_door","localizedName":"Oak Door","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_door"},{"id":"minecraft:oak_fence","localizedName":"Oak Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence"},{"id":"minecraft:oak_fence_gate","localizedName":"Oak Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_fence_gate"},{"id":"minecraft:oak_hanging_sign","localizedName":"Oak Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.oak_hanging_sign"},{"id":"minecraft:oak_leaves","localizedName":"Oak Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_leaves"},{"id":"minecraft:oak_log","localizedName":"Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_log"},{"id":"minecraft:oak_planks","localizedName":"Oak Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_planks"},{"id":"minecraft:oak_pressure_plate","localizedName":"Oak Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_pressure_plate"},{"id":"minecraft:oak_sapling","localizedName":"Oak Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_sapling"},{"id":"minecraft:oak_sign","localizedName":"Oak Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.oak_sign"},{"id":"minecraft:oak_slab","localizedName":"Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_slab"},{"id":"minecraft:oak_stairs","localizedName":"Oak Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_stairs"},{"id":"minecraft:oak_trapdoor","localizedName":"Oak Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_trapdoor"},{"id":"minecraft:oak_wood","localizedName":"Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.oak_wood"},{"id":"minecraft:observer","localizedName":"Observer","maxStackSize":64,"unlocalizedName":"block.minecraft.observer"},{"id":"minecraft:obsidian","localizedName":"Obsidian","maxStackSize":64,"unlocalizedName":"block.minecraft.obsidian"},{"id":"minecraft:ocelot_spawn_egg","localizedName":"Ocelot Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ocelot_spawn_egg"},{"id":"minecraft:ochre_froglight","localizedName":"Ochre Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.ochre_froglight"},{"id":"minecraft:ominous_bottle","localizedName":"Ominous Bottle","maxStackSize":64,"unlocalizedName":"item.minecraft.ominous_bottle"},{"id":"minecraft:ominous_trial_key","localizedName":"Ominous Trial Key","maxStackSize":64,"unlocalizedName":"item.minecraft.ominous_trial_key"},{"id":"minecraft:orange_banner","localizedName":"Orange Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.orange_banner"},{"id":"minecraft:orange_bed","localizedName":"Orange Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.orange_bed"},{"id":"minecraft:orange_bundle","localizedName":"Orange Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.orange_bundle"},{"id":"minecraft:orange_candle","localizedName":"Orange Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_candle"},{"id":"minecraft:orange_carpet","localizedName":"Orange Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_carpet"},{"id":"minecraft:orange_concrete","localizedName":"Orange Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete"},{"id":"minecraft:orange_concrete_powder","localizedName":"Orange Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_concrete_powder"},{"id":"minecraft:orange_dye","localizedName":"Orange Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.orange_dye"},{"id":"minecraft:orange_glazed_terracotta","localizedName":"Orange Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_glazed_terracotta"},{"id":"minecraft:orange_shulker_box","localizedName":"Orange Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.orange_shulker_box"},{"id":"minecraft:orange_stained_glass","localizedName":"Orange Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass"},{"id":"minecraft:orange_stained_glass_pane","localizedName":"Orange Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_stained_glass_pane"},{"id":"minecraft:orange_terracotta","localizedName":"Orange Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_terracotta"},{"id":"minecraft:orange_tulip","localizedName":"Orange Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_tulip"},{"id":"minecraft:orange_wool","localizedName":"Orange Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.orange_wool"},{"id":"minecraft:oxeye_daisy","localizedName":"Oxeye Daisy","maxStackSize":64,"unlocalizedName":"block.minecraft.oxeye_daisy"},{"id":"minecraft:oxidized_chiseled_copper","localizedName":"Oxidized Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_chiseled_copper"},{"id":"minecraft:oxidized_copper","localizedName":"Oxidized Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper"},{"id":"minecraft:oxidized_copper_bulb","localizedName":"Oxidized Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_bulb"},{"id":"minecraft:oxidized_copper_door","localizedName":"Oxidized Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_door"},{"id":"minecraft:oxidized_copper_grate","localizedName":"Oxidized Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_grate"},{"id":"minecraft:oxidized_copper_trapdoor","localizedName":"Oxidized Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_copper_trapdoor"},{"id":"minecraft:oxidized_cut_copper","localizedName":"Oxidized Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper"},{"id":"minecraft:oxidized_cut_copper_slab","localizedName":"Oxidized Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_slab"},{"id":"minecraft:oxidized_cut_copper_stairs","localizedName":"Oxidized Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.oxidized_cut_copper_stairs"},{"id":"minecraft:packed_ice","localizedName":"Packed Ice","maxStackSize":64,"unlocalizedName":"block.minecraft.packed_ice"},{"id":"minecraft:packed_mud","localizedName":"Packed Mud","maxStackSize":64,"unlocalizedName":"block.minecraft.packed_mud"},{"id":"minecraft:painting","localizedName":"Painting","maxStackSize":64,"unlocalizedName":"item.minecraft.painting"},{"id":"minecraft:pale_hanging_moss","localizedName":"Pale Hanging Moss","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_hanging_moss"},{"id":"minecraft:pale_moss_block","localizedName":"Pale Moss Block","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_moss_block"},{"id":"minecraft:pale_moss_carpet","localizedName":"Pale Moss Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_moss_carpet"},{"id":"minecraft:pale_oak_boat","localizedName":"Pale Oak Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.pale_oak_boat"},{"id":"minecraft:pale_oak_button","localizedName":"Pale Oak Button","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_button"},{"id":"minecraft:pale_oak_chest_boat","localizedName":"Pale Oak Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.pale_oak_chest_boat"},{"id":"minecraft:pale_oak_door","localizedName":"Pale Oak Door","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_door"},{"id":"minecraft:pale_oak_fence","localizedName":"Pale Oak Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_fence"},{"id":"minecraft:pale_oak_fence_gate","localizedName":"Pale Oak Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_fence_gate"},{"id":"minecraft:pale_oak_hanging_sign","localizedName":"Pale Oak Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.pale_oak_hanging_sign"},{"id":"minecraft:pale_oak_leaves","localizedName":"Pale Oak Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_leaves"},{"id":"minecraft:pale_oak_log","localizedName":"Pale Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_log"},{"id":"minecraft:pale_oak_planks","localizedName":"Pale Oak Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_planks"},{"id":"minecraft:pale_oak_pressure_plate","localizedName":"Pale Oak Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_pressure_plate"},{"id":"minecraft:pale_oak_sapling","localizedName":"Pale Oak Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_sapling"},{"id":"minecraft:pale_oak_sign","localizedName":"Pale Oak Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.pale_oak_sign"},{"id":"minecraft:pale_oak_slab","localizedName":"Pale Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_slab"},{"id":"minecraft:pale_oak_stairs","localizedName":"Pale Oak Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_stairs"},{"id":"minecraft:pale_oak_trapdoor","localizedName":"Pale Oak Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_trapdoor"},{"id":"minecraft:pale_oak_wood","localizedName":"Pale Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.pale_oak_wood"},{"id":"minecraft:panda_spawn_egg","localizedName":"Panda Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.panda_spawn_egg"},{"id":"minecraft:paper","localizedName":"Paper","maxStackSize":64,"unlocalizedName":"item.minecraft.paper"},{"id":"minecraft:parrot_spawn_egg","localizedName":"Parrot Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.parrot_spawn_egg"},{"id":"minecraft:pearlescent_froglight","localizedName":"Pearlescent Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.pearlescent_froglight"},{"id":"minecraft:peony","localizedName":"Peony","maxStackSize":64,"unlocalizedName":"block.minecraft.peony"},{"id":"minecraft:petrified_oak_slab","localizedName":"Petrified Oak Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.petrified_oak_slab"},{"id":"minecraft:phantom_membrane","localizedName":"Phantom Membrane","maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_membrane"},{"id":"minecraft:phantom_spawn_egg","localizedName":"Phantom Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.phantom_spawn_egg"},{"id":"minecraft:pig_spawn_egg","localizedName":"Pig Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pig_spawn_egg"},{"id":"minecraft:piglin_banner_pattern","localizedName":"Snout Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.piglin_banner_pattern"},{"id":"minecraft:piglin_brute_spawn_egg","localizedName":"Piglin Brute Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_brute_spawn_egg"},{"id":"minecraft:piglin_head","localizedName":"Piglin Head","maxStackSize":64,"unlocalizedName":"block.minecraft.piglin_head"},{"id":"minecraft:piglin_spawn_egg","localizedName":"Piglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.piglin_spawn_egg"},{"id":"minecraft:pillager_spawn_egg","localizedName":"Pillager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pillager_spawn_egg"},{"id":"minecraft:pink_banner","localizedName":"Pink Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.pink_banner"},{"id":"minecraft:pink_bed","localizedName":"Pink Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.pink_bed"},{"id":"minecraft:pink_bundle","localizedName":"Pink Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.pink_bundle"},{"id":"minecraft:pink_candle","localizedName":"Pink Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_candle"},{"id":"minecraft:pink_carpet","localizedName":"Pink Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_carpet"},{"id":"minecraft:pink_concrete","localizedName":"Pink Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete"},{"id":"minecraft:pink_concrete_powder","localizedName":"Pink Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_concrete_powder"},{"id":"minecraft:pink_dye","localizedName":"Pink Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.pink_dye"},{"id":"minecraft:pink_glazed_terracotta","localizedName":"Pink Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_glazed_terracotta"},{"id":"minecraft:pink_petals","localizedName":"Pink Petals","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_petals"},{"id":"minecraft:pink_shulker_box","localizedName":"Pink Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.pink_shulker_box"},{"id":"minecraft:pink_stained_glass","localizedName":"Pink Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass"},{"id":"minecraft:pink_stained_glass_pane","localizedName":"Pink Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_stained_glass_pane"},{"id":"minecraft:pink_terracotta","localizedName":"Pink Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_terracotta"},{"id":"minecraft:pink_tulip","localizedName":"Pink Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_tulip"},{"id":"minecraft:pink_wool","localizedName":"Pink Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.pink_wool"},{"id":"minecraft:piston","localizedName":"Piston","maxStackSize":64,"unlocalizedName":"block.minecraft.piston"},{"id":"minecraft:pitcher_plant","localizedName":"Pitcher Plant","maxStackSize":64,"unlocalizedName":"block.minecraft.pitcher_plant"},{"id":"minecraft:pitcher_pod","localizedName":"Pitcher Pod","maxStackSize":64,"unlocalizedName":"item.minecraft.pitcher_pod"},{"id":"minecraft:player_head","localizedName":"Player Head","maxStackSize":64,"unlocalizedName":"block.minecraft.player_head"},{"id":"minecraft:plenty_pottery_sherd","localizedName":"Plenty Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.plenty_pottery_sherd"},{"id":"minecraft:podzol","localizedName":"Podzol","maxStackSize":64,"unlocalizedName":"block.minecraft.podzol"},{"id":"minecraft:pointed_dripstone","localizedName":"Pointed Dripstone","maxStackSize":64,"unlocalizedName":"block.minecraft.pointed_dripstone"},{"id":"minecraft:poisonous_potato","localizedName":"Poisonous Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.poisonous_potato"},{"id":"minecraft:polar_bear_spawn_egg","localizedName":"Polar Bear Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.polar_bear_spawn_egg"},{"id":"minecraft:polished_andesite","localizedName":"Polished Andesite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite"},{"id":"minecraft:polished_andesite_slab","localizedName":"Polished Andesite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_slab"},{"id":"minecraft:polished_andesite_stairs","localizedName":"Polished Andesite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_andesite_stairs"},{"id":"minecraft:polished_basalt","localizedName":"Polished Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_basalt"},{"id":"minecraft:polished_blackstone","localizedName":"Polished Blackstone","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone"},{"id":"minecraft:polished_blackstone_brick_slab","localizedName":"Polished Blackstone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_slab"},{"id":"minecraft:polished_blackstone_brick_stairs","localizedName":"Polished Blackstone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_stairs"},{"id":"minecraft:polished_blackstone_brick_wall","localizedName":"Polished Blackstone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_brick_wall"},{"id":"minecraft:polished_blackstone_bricks","localizedName":"Polished Blackstone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_bricks"},{"id":"minecraft:polished_blackstone_button","localizedName":"Polished Blackstone Button","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_button"},{"id":"minecraft:polished_blackstone_pressure_plate","localizedName":"Polished Blackstone Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_pressure_plate"},{"id":"minecraft:polished_blackstone_slab","localizedName":"Polished Blackstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_slab"},{"id":"minecraft:polished_blackstone_stairs","localizedName":"Polished Blackstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_stairs"},{"id":"minecraft:polished_blackstone_wall","localizedName":"Polished Blackstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_blackstone_wall"},{"id":"minecraft:polished_deepslate","localizedName":"Polished Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate"},{"id":"minecraft:polished_deepslate_slab","localizedName":"Polished Deepslate Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_slab"},{"id":"minecraft:polished_deepslate_stairs","localizedName":"Polished Deepslate Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_stairs"},{"id":"minecraft:polished_deepslate_wall","localizedName":"Polished Deepslate Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_deepslate_wall"},{"id":"minecraft:polished_diorite","localizedName":"Polished Diorite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite"},{"id":"minecraft:polished_diorite_slab","localizedName":"Polished Diorite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_slab"},{"id":"minecraft:polished_diorite_stairs","localizedName":"Polished Diorite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_diorite_stairs"},{"id":"minecraft:polished_granite","localizedName":"Polished Granite","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite"},{"id":"minecraft:polished_granite_slab","localizedName":"Polished Granite Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_slab"},{"id":"minecraft:polished_granite_stairs","localizedName":"Polished Granite Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_granite_stairs"},{"id":"minecraft:polished_tuff","localizedName":"Polished Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff"},{"id":"minecraft:polished_tuff_slab","localizedName":"Polished Tuff Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_slab"},{"id":"minecraft:polished_tuff_stairs","localizedName":"Polished Tuff Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_stairs"},{"id":"minecraft:polished_tuff_wall","localizedName":"Polished Tuff Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.polished_tuff_wall"},{"id":"minecraft:popped_chorus_fruit","localizedName":"Popped Chorus Fruit","maxStackSize":64,"unlocalizedName":"item.minecraft.popped_chorus_fruit"},{"id":"minecraft:poppy","localizedName":"Poppy","maxStackSize":64,"unlocalizedName":"block.minecraft.poppy"},{"id":"minecraft:porkchop","localizedName":"Raw Porkchop","maxStackSize":64,"unlocalizedName":"item.minecraft.porkchop"},{"id":"minecraft:potato","localizedName":"Potato","maxStackSize":64,"unlocalizedName":"item.minecraft.potato"},{"id":"minecraft:potion","localizedName":"Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.potion"},{"id":"minecraft:powder_snow_bucket","localizedName":"Powder Snow Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.powder_snow_bucket"},{"id":"minecraft:powered_rail","localizedName":"Powered Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.powered_rail"},{"id":"minecraft:prismarine","localizedName":"Prismarine","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine"},{"id":"minecraft:prismarine_brick_slab","localizedName":"Prismarine Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_slab"},{"id":"minecraft:prismarine_brick_stairs","localizedName":"Prismarine Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_brick_stairs"},{"id":"minecraft:prismarine_bricks","localizedName":"Prismarine Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_bricks"},{"id":"minecraft:prismarine_crystals","localizedName":"Prismarine Crystals","maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_crystals"},{"id":"minecraft:prismarine_shard","localizedName":"Prismarine Shard","maxStackSize":64,"unlocalizedName":"item.minecraft.prismarine_shard"},{"id":"minecraft:prismarine_slab","localizedName":"Prismarine Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_slab"},{"id":"minecraft:prismarine_stairs","localizedName":"Prismarine Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_stairs"},{"id":"minecraft:prismarine_wall","localizedName":"Prismarine Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.prismarine_wall"},{"id":"minecraft:prize_pottery_sherd","localizedName":"Prize Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.prize_pottery_sherd"},{"id":"minecraft:pufferfish","localizedName":"Pufferfish","maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish"},{"id":"minecraft:pufferfish_bucket","localizedName":"Bucket of Pufferfish","maxStackSize":1,"unlocalizedName":"item.minecraft.pufferfish_bucket"},{"id":"minecraft:pufferfish_spawn_egg","localizedName":"Pufferfish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.pufferfish_spawn_egg"},{"id":"minecraft:pumpkin","localizedName":"Pumpkin","maxStackSize":64,"unlocalizedName":"block.minecraft.pumpkin"},{"id":"minecraft:pumpkin_pie","localizedName":"Pumpkin Pie","maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_pie"},{"id":"minecraft:pumpkin_seeds","localizedName":"Pumpkin Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.pumpkin_seeds"},{"id":"minecraft:purple_banner","localizedName":"Purple Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.purple_banner"},{"id":"minecraft:purple_bed","localizedName":"Purple Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.purple_bed"},{"id":"minecraft:purple_bundle","localizedName":"Purple Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.purple_bundle"},{"id":"minecraft:purple_candle","localizedName":"Purple Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_candle"},{"id":"minecraft:purple_carpet","localizedName":"Purple Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_carpet"},{"id":"minecraft:purple_concrete","localizedName":"Purple Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete"},{"id":"minecraft:purple_concrete_powder","localizedName":"Purple Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_concrete_powder"},{"id":"minecraft:purple_dye","localizedName":"Purple Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.purple_dye"},{"id":"minecraft:purple_glazed_terracotta","localizedName":"Purple Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_glazed_terracotta"},{"id":"minecraft:purple_shulker_box","localizedName":"Purple Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.purple_shulker_box"},{"id":"minecraft:purple_stained_glass","localizedName":"Purple Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass"},{"id":"minecraft:purple_stained_glass_pane","localizedName":"Purple Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_stained_glass_pane"},{"id":"minecraft:purple_terracotta","localizedName":"Purple Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_terracotta"},{"id":"minecraft:purple_wool","localizedName":"Purple Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.purple_wool"},{"id":"minecraft:purpur_block","localizedName":"Purpur Block","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_block"},{"id":"minecraft:purpur_pillar","localizedName":"Purpur Pillar","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_pillar"},{"id":"minecraft:purpur_slab","localizedName":"Purpur Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_slab"},{"id":"minecraft:purpur_stairs","localizedName":"Purpur Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.purpur_stairs"},{"id":"minecraft:quartz","localizedName":"Nether Quartz","maxStackSize":64,"unlocalizedName":"item.minecraft.quartz"},{"id":"minecraft:quartz_block","localizedName":"Block of Quartz","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_block"},{"id":"minecraft:quartz_bricks","localizedName":"Quartz Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_bricks"},{"id":"minecraft:quartz_pillar","localizedName":"Quartz Pillar","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_pillar"},{"id":"minecraft:quartz_slab","localizedName":"Quartz Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_slab"},{"id":"minecraft:quartz_stairs","localizedName":"Quartz Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.quartz_stairs"},{"id":"minecraft:rabbit","localizedName":"Raw Rabbit","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit"},{"id":"minecraft:rabbit_foot","localizedName":"Rabbit\u0027s Foot","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_foot"},{"id":"minecraft:rabbit_hide","localizedName":"Rabbit Hide","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_hide"},{"id":"minecraft:rabbit_spawn_egg","localizedName":"Rabbit Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.rabbit_spawn_egg"},{"id":"minecraft:rabbit_stew","localizedName":"Rabbit Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.rabbit_stew"},{"id":"minecraft:rail","localizedName":"Rail","maxStackSize":64,"unlocalizedName":"block.minecraft.rail"},{"id":"minecraft:raiser_armor_trim_smithing_template","localizedName":"Raiser Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.raiser_armor_trim_smithing_template"},{"id":"minecraft:ravager_spawn_egg","localizedName":"Ravager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.ravager_spawn_egg"},{"id":"minecraft:raw_copper","localizedName":"Raw Copper","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_copper"},{"id":"minecraft:raw_copper_block","localizedName":"Block of Raw Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_copper_block"},{"id":"minecraft:raw_gold","localizedName":"Raw Gold","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_gold"},{"id":"minecraft:raw_gold_block","localizedName":"Block of Raw Gold","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_gold_block"},{"id":"minecraft:raw_iron","localizedName":"Raw Iron","maxStackSize":64,"unlocalizedName":"item.minecraft.raw_iron"},{"id":"minecraft:raw_iron_block","localizedName":"Block of Raw Iron","maxStackSize":64,"unlocalizedName":"block.minecraft.raw_iron_block"},{"id":"minecraft:recovery_compass","localizedName":"Recovery Compass","maxStackSize":64,"unlocalizedName":"item.minecraft.recovery_compass"},{"id":"minecraft:red_banner","localizedName":"Red Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.red_banner"},{"id":"minecraft:red_bed","localizedName":"Red Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.red_bed"},{"id":"minecraft:red_bundle","localizedName":"Red Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.red_bundle"},{"id":"minecraft:red_candle","localizedName":"Red Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.red_candle"},{"id":"minecraft:red_carpet","localizedName":"Red Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.red_carpet"},{"id":"minecraft:red_concrete","localizedName":"Red Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete"},{"id":"minecraft:red_concrete_powder","localizedName":"Red Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.red_concrete_powder"},{"id":"minecraft:red_dye","localizedName":"Red Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.red_dye"},{"id":"minecraft:red_glazed_terracotta","localizedName":"Red Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.red_glazed_terracotta"},{"id":"minecraft:red_mushroom","localizedName":"Red Mushroom","maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom"},{"id":"minecraft:red_mushroom_block","localizedName":"Red Mushroom Block","maxStackSize":64,"unlocalizedName":"block.minecraft.red_mushroom_block"},{"id":"minecraft:red_nether_brick_slab","localizedName":"Red Nether Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_slab"},{"id":"minecraft:red_nether_brick_stairs","localizedName":"Red Nether Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_stairs"},{"id":"minecraft:red_nether_brick_wall","localizedName":"Red Nether Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_brick_wall"},{"id":"minecraft:red_nether_bricks","localizedName":"Red Nether Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.red_nether_bricks"},{"id":"minecraft:red_sand","localizedName":"Red Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sand"},{"id":"minecraft:red_sandstone","localizedName":"Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone"},{"id":"minecraft:red_sandstone_slab","localizedName":"Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_slab"},{"id":"minecraft:red_sandstone_stairs","localizedName":"Red Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_stairs"},{"id":"minecraft:red_sandstone_wall","localizedName":"Red Sandstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.red_sandstone_wall"},{"id":"minecraft:red_shulker_box","localizedName":"Red Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.red_shulker_box"},{"id":"minecraft:red_stained_glass","localizedName":"Red Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass"},{"id":"minecraft:red_stained_glass_pane","localizedName":"Red Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.red_stained_glass_pane"},{"id":"minecraft:red_terracotta","localizedName":"Red Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.red_terracotta"},{"id":"minecraft:red_tulip","localizedName":"Red Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.red_tulip"},{"id":"minecraft:red_wool","localizedName":"Red Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.red_wool"},{"id":"minecraft:redstone","localizedName":"Redstone Dust","maxStackSize":64,"unlocalizedName":"item.minecraft.redstone"},{"id":"minecraft:redstone_block","localizedName":"Block of Redstone","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_block"},{"id":"minecraft:redstone_lamp","localizedName":"Redstone Lamp","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_lamp"},{"id":"minecraft:redstone_ore","localizedName":"Redstone Ore","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_ore"},{"id":"minecraft:redstone_torch","localizedName":"Redstone Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.redstone_torch"},{"id":"minecraft:reinforced_deepslate","localizedName":"Reinforced Deepslate","maxStackSize":64,"unlocalizedName":"block.minecraft.reinforced_deepslate"},{"id":"minecraft:repeater","localizedName":"Redstone Repeater","maxStackSize":64,"unlocalizedName":"block.minecraft.repeater"},{"id":"minecraft:repeating_command_block","localizedName":"Repeating Command Block","maxStackSize":64,"unlocalizedName":"block.minecraft.repeating_command_block"},{"id":"minecraft:respawn_anchor","localizedName":"Respawn Anchor","maxStackSize":64,"unlocalizedName":"block.minecraft.respawn_anchor"},{"id":"minecraft:rib_armor_trim_smithing_template","localizedName":"Rib Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.rib_armor_trim_smithing_template"},{"id":"minecraft:rooted_dirt","localizedName":"Rooted Dirt","maxStackSize":64,"unlocalizedName":"block.minecraft.rooted_dirt"},{"id":"minecraft:rose_bush","localizedName":"Rose Bush","maxStackSize":64,"unlocalizedName":"block.minecraft.rose_bush"},{"id":"minecraft:rotten_flesh","localizedName":"Rotten Flesh","maxStackSize":64,"unlocalizedName":"item.minecraft.rotten_flesh"},{"id":"minecraft:saddle","localizedName":"Saddle","maxStackSize":1,"unlocalizedName":"item.minecraft.saddle"},{"id":"minecraft:salmon","localizedName":"Raw Salmon","maxStackSize":64,"unlocalizedName":"item.minecraft.salmon"},{"id":"minecraft:salmon_bucket","localizedName":"Bucket of Salmon","maxStackSize":1,"unlocalizedName":"item.minecraft.salmon_bucket"},{"id":"minecraft:salmon_spawn_egg","localizedName":"Salmon Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.salmon_spawn_egg"},{"id":"minecraft:sand","localizedName":"Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.sand"},{"id":"minecraft:sandstone","localizedName":"Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone"},{"id":"minecraft:sandstone_slab","localizedName":"Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_slab"},{"id":"minecraft:sandstone_stairs","localizedName":"Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_stairs"},{"id":"minecraft:sandstone_wall","localizedName":"Sandstone Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.sandstone_wall"},{"id":"minecraft:scaffolding","localizedName":"Scaffolding","maxStackSize":64,"unlocalizedName":"block.minecraft.scaffolding"},{"id":"minecraft:scrape_pottery_sherd","localizedName":"Scrape Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.scrape_pottery_sherd"},{"id":"minecraft:sculk","localizedName":"Sculk","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk"},{"id":"minecraft:sculk_catalyst","localizedName":"Sculk Catalyst","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_catalyst"},{"id":"minecraft:sculk_sensor","localizedName":"Sculk Sensor","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_sensor"},{"id":"minecraft:sculk_shrieker","localizedName":"Sculk Shrieker","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_shrieker"},{"id":"minecraft:sculk_vein","localizedName":"Sculk Vein","maxStackSize":64,"unlocalizedName":"block.minecraft.sculk_vein"},{"id":"minecraft:sea_lantern","localizedName":"Sea Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.sea_lantern"},{"id":"minecraft:sea_pickle","localizedName":"Sea Pickle","maxStackSize":64,"unlocalizedName":"block.minecraft.sea_pickle"},{"id":"minecraft:seagrass","localizedName":"Seagrass","maxStackSize":64,"unlocalizedName":"block.minecraft.seagrass"},{"id":"minecraft:sentry_armor_trim_smithing_template","localizedName":"Sentry Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.sentry_armor_trim_smithing_template"},{"id":"minecraft:shaper_armor_trim_smithing_template","localizedName":"Shaper Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.shaper_armor_trim_smithing_template"},{"id":"minecraft:sheaf_pottery_sherd","localizedName":"Sheaf Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.sheaf_pottery_sherd"},{"id":"minecraft:shears","localizedName":"Shears","maxDamage":238,"maxStackSize":1,"unlocalizedName":"item.minecraft.shears"},{"id":"minecraft:sheep_spawn_egg","localizedName":"Sheep Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.sheep_spawn_egg"},{"id":"minecraft:shelter_pottery_sherd","localizedName":"Shelter Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.shelter_pottery_sherd"},{"id":"minecraft:shield","localizedName":"Shield","maxDamage":336,"maxStackSize":1,"unlocalizedName":"item.minecraft.shield"},{"id":"minecraft:short_grass","localizedName":"Short Grass","maxStackSize":64,"unlocalizedName":"block.minecraft.short_grass"},{"id":"minecraft:shroomlight","localizedName":"Shroomlight","maxStackSize":64,"unlocalizedName":"block.minecraft.shroomlight"},{"id":"minecraft:shulker_box","localizedName":"Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.shulker_box"},{"id":"minecraft:shulker_shell","localizedName":"Shulker Shell","maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_shell"},{"id":"minecraft:shulker_spawn_egg","localizedName":"Shulker Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.shulker_spawn_egg"},{"id":"minecraft:silence_armor_trim_smithing_template","localizedName":"Silence Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.silence_armor_trim_smithing_template"},{"id":"minecraft:silverfish_spawn_egg","localizedName":"Silverfish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.silverfish_spawn_egg"},{"id":"minecraft:skeleton_horse_spawn_egg","localizedName":"Skeleton Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_horse_spawn_egg"},{"id":"minecraft:skeleton_skull","localizedName":"Skeleton Skull","maxStackSize":64,"unlocalizedName":"block.minecraft.skeleton_skull"},{"id":"minecraft:skeleton_spawn_egg","localizedName":"Skeleton Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.skeleton_spawn_egg"},{"id":"minecraft:skull_banner_pattern","localizedName":"Skull Charge Banner Pattern","maxStackSize":1,"unlocalizedName":"item.minecraft.skull_banner_pattern"},{"id":"minecraft:skull_pottery_sherd","localizedName":"Skull Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.skull_pottery_sherd"},{"id":"minecraft:slime_ball","localizedName":"Slimeball","maxStackSize":64,"unlocalizedName":"item.minecraft.slime_ball"},{"id":"minecraft:slime_block","localizedName":"Slime Block","maxStackSize":64,"unlocalizedName":"block.minecraft.slime_block"},{"id":"minecraft:slime_spawn_egg","localizedName":"Slime Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.slime_spawn_egg"},{"id":"minecraft:small_amethyst_bud","localizedName":"Small Amethyst Bud","maxStackSize":64,"unlocalizedName":"block.minecraft.small_amethyst_bud"},{"id":"minecraft:small_dripleaf","localizedName":"Small Dripleaf","maxStackSize":64,"unlocalizedName":"block.minecraft.small_dripleaf"},{"id":"minecraft:smithing_table","localizedName":"Smithing Table","maxStackSize":64,"unlocalizedName":"block.minecraft.smithing_table"},{"id":"minecraft:smoker","localizedName":"Smoker","maxStackSize":64,"unlocalizedName":"block.minecraft.smoker"},{"id":"minecraft:smooth_basalt","localizedName":"Smooth Basalt","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_basalt"},{"id":"minecraft:smooth_quartz","localizedName":"Smooth Quartz Block","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz"},{"id":"minecraft:smooth_quartz_slab","localizedName":"Smooth Quartz Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_slab"},{"id":"minecraft:smooth_quartz_stairs","localizedName":"Smooth Quartz Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_quartz_stairs"},{"id":"minecraft:smooth_red_sandstone","localizedName":"Smooth Red Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone"},{"id":"minecraft:smooth_red_sandstone_slab","localizedName":"Smooth Red Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_slab"},{"id":"minecraft:smooth_red_sandstone_stairs","localizedName":"Smooth Red Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_red_sandstone_stairs"},{"id":"minecraft:smooth_sandstone","localizedName":"Smooth Sandstone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone"},{"id":"minecraft:smooth_sandstone_slab","localizedName":"Smooth Sandstone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_slab"},{"id":"minecraft:smooth_sandstone_stairs","localizedName":"Smooth Sandstone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_sandstone_stairs"},{"id":"minecraft:smooth_stone","localizedName":"Smooth Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone"},{"id":"minecraft:smooth_stone_slab","localizedName":"Smooth Stone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.smooth_stone_slab"},{"id":"minecraft:sniffer_egg","localizedName":"Sniffer Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.sniffer_egg"},{"id":"minecraft:sniffer_spawn_egg","localizedName":"Sniffer Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.sniffer_spawn_egg"},{"id":"minecraft:snort_pottery_sherd","localizedName":"Snort Pottery Sherd","maxStackSize":64,"unlocalizedName":"item.minecraft.snort_pottery_sherd"},{"id":"minecraft:snout_armor_trim_smithing_template","localizedName":"Snout Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.snout_armor_trim_smithing_template"},{"id":"minecraft:snow","localizedName":"Snow","maxStackSize":64,"unlocalizedName":"block.minecraft.snow"},{"id":"minecraft:snow_block","localizedName":"Snow Block","maxStackSize":64,"unlocalizedName":"block.minecraft.snow_block"},{"id":"minecraft:snow_golem_spawn_egg","localizedName":"Snow Golem Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.snow_golem_spawn_egg"},{"id":"minecraft:snowball","localizedName":"Snowball","maxStackSize":16,"unlocalizedName":"item.minecraft.snowball"},{"id":"minecraft:soul_campfire","localizedName":"Soul Campfire","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_campfire"},{"id":"minecraft:soul_lantern","localizedName":"Soul Lantern","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_lantern"},{"id":"minecraft:soul_sand","localizedName":"Soul Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_sand"},{"id":"minecraft:soul_soil","localizedName":"Soul Soil","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_soil"},{"id":"minecraft:soul_torch","localizedName":"Soul Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.soul_torch"},{"id":"minecraft:spawner","localizedName":"Monster Spawner","maxStackSize":64,"unlocalizedName":"block.minecraft.spawner"},{"id":"minecraft:spectral_arrow","localizedName":"Spectral Arrow","maxStackSize":64,"unlocalizedName":"item.minecraft.spectral_arrow"},{"id":"minecraft:spider_eye","localizedName":"Spider Eye","maxStackSize":64,"unlocalizedName":"item.minecraft.spider_eye"},{"id":"minecraft:spider_spawn_egg","localizedName":"Spider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.spider_spawn_egg"},{"id":"minecraft:spire_armor_trim_smithing_template","localizedName":"Spire Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.spire_armor_trim_smithing_template"},{"id":"minecraft:splash_potion","localizedName":"Splash Water Bottle","maxStackSize":1,"unlocalizedName":"item.minecraft.splash_potion"},{"id":"minecraft:sponge","localizedName":"Sponge","maxStackSize":64,"unlocalizedName":"block.minecraft.sponge"},{"id":"minecraft:spore_blossom","localizedName":"Spore Blossom","maxStackSize":64,"unlocalizedName":"block.minecraft.spore_blossom"},{"id":"minecraft:spruce_boat","localizedName":"Spruce Boat","maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_boat"},{"id":"minecraft:spruce_button","localizedName":"Spruce Button","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_button"},{"id":"minecraft:spruce_chest_boat","localizedName":"Spruce Boat with Chest","maxStackSize":1,"unlocalizedName":"item.minecraft.spruce_chest_boat"},{"id":"minecraft:spruce_door","localizedName":"Spruce Door","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_door"},{"id":"minecraft:spruce_fence","localizedName":"Spruce Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence"},{"id":"minecraft:spruce_fence_gate","localizedName":"Spruce Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_fence_gate"},{"id":"minecraft:spruce_hanging_sign","localizedName":"Spruce Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_hanging_sign"},{"id":"minecraft:spruce_leaves","localizedName":"Spruce Leaves","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_leaves"},{"id":"minecraft:spruce_log","localizedName":"Spruce Log","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_log"},{"id":"minecraft:spruce_planks","localizedName":"Spruce Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_planks"},{"id":"minecraft:spruce_pressure_plate","localizedName":"Spruce Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_pressure_plate"},{"id":"minecraft:spruce_sapling","localizedName":"Spruce Sapling","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_sapling"},{"id":"minecraft:spruce_sign","localizedName":"Spruce Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.spruce_sign"},{"id":"minecraft:spruce_slab","localizedName":"Spruce Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_slab"},{"id":"minecraft:spruce_stairs","localizedName":"Spruce Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_stairs"},{"id":"minecraft:spruce_trapdoor","localizedName":"Spruce Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_trapdoor"},{"id":"minecraft:spruce_wood","localizedName":"Spruce Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.spruce_wood"},{"id":"minecraft:spyglass","localizedName":"Spyglass","maxStackSize":1,"unlocalizedName":"item.minecraft.spyglass"},{"id":"minecraft:squid_spawn_egg","localizedName":"Squid Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.squid_spawn_egg"},{"id":"minecraft:stick","localizedName":"Stick","maxStackSize":64,"unlocalizedName":"item.minecraft.stick"},{"id":"minecraft:sticky_piston","localizedName":"Sticky Piston","maxStackSize":64,"unlocalizedName":"block.minecraft.sticky_piston"},{"id":"minecraft:stone","localizedName":"Stone","maxStackSize":64,"unlocalizedName":"block.minecraft.stone"},{"id":"minecraft:stone_axe","localizedName":"Stone Axe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_axe"},{"id":"minecraft:stone_brick_slab","localizedName":"Stone Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_slab"},{"id":"minecraft:stone_brick_stairs","localizedName":"Stone Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_stairs"},{"id":"minecraft:stone_brick_wall","localizedName":"Stone Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_brick_wall"},{"id":"minecraft:stone_bricks","localizedName":"Stone Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_bricks"},{"id":"minecraft:stone_button","localizedName":"Stone Button","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_button"},{"id":"minecraft:stone_hoe","localizedName":"Stone Hoe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_hoe"},{"id":"minecraft:stone_pickaxe","localizedName":"Stone Pickaxe","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_pickaxe"},{"id":"minecraft:stone_pressure_plate","localizedName":"Stone Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_pressure_plate"},{"id":"minecraft:stone_shovel","localizedName":"Stone Shovel","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_shovel"},{"id":"minecraft:stone_slab","localizedName":"Stone Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_slab"},{"id":"minecraft:stone_stairs","localizedName":"Stone Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.stone_stairs"},{"id":"minecraft:stone_sword","localizedName":"Stone Sword","maxDamage":131,"maxStackSize":1,"unlocalizedName":"item.minecraft.stone_sword"},{"id":"minecraft:stonecutter","localizedName":"Stonecutter","maxStackSize":64,"unlocalizedName":"block.minecraft.stonecutter"},{"id":"minecraft:stray_spawn_egg","localizedName":"Stray Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.stray_spawn_egg"},{"id":"minecraft:strider_spawn_egg","localizedName":"Strider Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.strider_spawn_egg"},{"id":"minecraft:string","localizedName":"String","maxStackSize":64,"unlocalizedName":"item.minecraft.string"},{"id":"minecraft:stripped_acacia_log","localizedName":"Stripped Acacia Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_log"},{"id":"minecraft:stripped_acacia_wood","localizedName":"Stripped Acacia Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_acacia_wood"},{"id":"minecraft:stripped_bamboo_block","localizedName":"Block of Stripped Bamboo","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_bamboo_block"},{"id":"minecraft:stripped_birch_log","localizedName":"Stripped Birch Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_log"},{"id":"minecraft:stripped_birch_wood","localizedName":"Stripped Birch Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_birch_wood"},{"id":"minecraft:stripped_cherry_log","localizedName":"Stripped Cherry Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_cherry_log"},{"id":"minecraft:stripped_cherry_wood","localizedName":"Stripped Cherry Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_cherry_wood"},{"id":"minecraft:stripped_crimson_hyphae","localizedName":"Stripped Crimson Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_hyphae"},{"id":"minecraft:stripped_crimson_stem","localizedName":"Stripped Crimson Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_crimson_stem"},{"id":"minecraft:stripped_dark_oak_log","localizedName":"Stripped Dark Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_log"},{"id":"minecraft:stripped_dark_oak_wood","localizedName":"Stripped Dark Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_dark_oak_wood"},{"id":"minecraft:stripped_jungle_log","localizedName":"Stripped Jungle Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_log"},{"id":"minecraft:stripped_jungle_wood","localizedName":"Stripped Jungle Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_jungle_wood"},{"id":"minecraft:stripped_mangrove_log","localizedName":"Stripped Mangrove Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_log"},{"id":"minecraft:stripped_mangrove_wood","localizedName":"Stripped Mangrove Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_mangrove_wood"},{"id":"minecraft:stripped_oak_log","localizedName":"Stripped Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_log"},{"id":"minecraft:stripped_oak_wood","localizedName":"Stripped Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_oak_wood"},{"id":"minecraft:stripped_pale_oak_log","localizedName":"Stripped Pale Oak Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_pale_oak_log"},{"id":"minecraft:stripped_pale_oak_wood","localizedName":"Stripped Pale Oak Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_pale_oak_wood"},{"id":"minecraft:stripped_spruce_log","localizedName":"Stripped Spruce Log","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_log"},{"id":"minecraft:stripped_spruce_wood","localizedName":"Stripped Spruce Wood","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_spruce_wood"},{"id":"minecraft:stripped_warped_hyphae","localizedName":"Stripped Warped Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_hyphae"},{"id":"minecraft:stripped_warped_stem","localizedName":"Stripped Warped Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.stripped_warped_stem"},{"id":"minecraft:structure_block","localizedName":"Structure Block","maxStackSize":64,"unlocalizedName":"block.minecraft.structure_block"},{"id":"minecraft:structure_void","localizedName":"Structure Void","maxStackSize":64,"unlocalizedName":"block.minecraft.structure_void"},{"id":"minecraft:sugar","localizedName":"Sugar","maxStackSize":64,"unlocalizedName":"item.minecraft.sugar"},{"id":"minecraft:sugar_cane","localizedName":"Sugar Cane","maxStackSize":64,"unlocalizedName":"block.minecraft.sugar_cane"},{"id":"minecraft:sunflower","localizedName":"Sunflower","maxStackSize":64,"unlocalizedName":"block.minecraft.sunflower"},{"id":"minecraft:suspicious_gravel","localizedName":"Suspicious Gravel","maxStackSize":64,"unlocalizedName":"block.minecraft.suspicious_gravel"},{"id":"minecraft:suspicious_sand","localizedName":"Suspicious Sand","maxStackSize":64,"unlocalizedName":"block.minecraft.suspicious_sand"},{"id":"minecraft:suspicious_stew","localizedName":"Suspicious Stew","maxStackSize":1,"unlocalizedName":"item.minecraft.suspicious_stew"},{"id":"minecraft:sweet_berries","localizedName":"Sweet Berries","maxStackSize":64,"unlocalizedName":"item.minecraft.sweet_berries"},{"id":"minecraft:tadpole_bucket","localizedName":"Bucket of Tadpole","maxStackSize":1,"unlocalizedName":"item.minecraft.tadpole_bucket"},{"id":"minecraft:tadpole_spawn_egg","localizedName":"Tadpole Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.tadpole_spawn_egg"},{"id":"minecraft:tall_grass","localizedName":"Tall Grass","maxStackSize":64,"unlocalizedName":"block.minecraft.tall_grass"},{"id":"minecraft:target","localizedName":"Target","maxStackSize":64,"unlocalizedName":"block.minecraft.target"},{"id":"minecraft:terracotta","localizedName":"Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.terracotta"},{"id":"minecraft:tide_armor_trim_smithing_template","localizedName":"Tide Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.tide_armor_trim_smithing_template"},{"id":"minecraft:tinted_glass","localizedName":"Tinted Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.tinted_glass"},{"id":"minecraft:tipped_arrow","localizedName":"Arrow of Poison","maxStackSize":64,"unlocalizedName":"item.minecraft.tipped_arrow"},{"id":"minecraft:tnt","localizedName":"TNT","maxStackSize":64,"unlocalizedName":"block.minecraft.tnt"},{"id":"minecraft:tnt_minecart","localizedName":"Minecart with TNT","maxStackSize":1,"unlocalizedName":"item.minecraft.tnt_minecart"},{"id":"minecraft:torch","localizedName":"Torch","maxStackSize":64,"unlocalizedName":"block.minecraft.torch"},{"id":"minecraft:torchflower","localizedName":"Torchflower","maxStackSize":64,"unlocalizedName":"block.minecraft.torchflower"},{"id":"minecraft:torchflower_seeds","localizedName":"Torchflower Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.torchflower_seeds"},{"id":"minecraft:totem_of_undying","localizedName":"Totem of Undying","maxStackSize":1,"unlocalizedName":"item.minecraft.totem_of_undying"},{"id":"minecraft:trader_llama_spawn_egg","localizedName":"Trader Llama Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.trader_llama_spawn_egg"},{"id":"minecraft:trapped_chest","localizedName":"Trapped Chest","maxStackSize":64,"unlocalizedName":"block.minecraft.trapped_chest"},{"id":"minecraft:trial_key","localizedName":"Trial Key","maxStackSize":64,"unlocalizedName":"item.minecraft.trial_key"},{"id":"minecraft:trial_spawner","localizedName":"Trial Spawner","maxStackSize":64,"unlocalizedName":"block.minecraft.trial_spawner"},{"id":"minecraft:trident","localizedName":"Trident","maxDamage":250,"maxStackSize":1,"unlocalizedName":"item.minecraft.trident"},{"id":"minecraft:tripwire_hook","localizedName":"Tripwire Hook","maxStackSize":64,"unlocalizedName":"block.minecraft.tripwire_hook"},{"id":"minecraft:tropical_fish","localizedName":"Tropical Fish","maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish"},{"id":"minecraft:tropical_fish_bucket","localizedName":"Bucket of Tropical Fish","maxStackSize":1,"unlocalizedName":"item.minecraft.tropical_fish_bucket"},{"id":"minecraft:tropical_fish_spawn_egg","localizedName":"Tropical Fish Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.tropical_fish_spawn_egg"},{"id":"minecraft:tube_coral","localizedName":"Tube Coral","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral"},{"id":"minecraft:tube_coral_block","localizedName":"Tube Coral Block","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_block"},{"id":"minecraft:tube_coral_fan","localizedName":"Tube Coral Fan","maxStackSize":64,"unlocalizedName":"block.minecraft.tube_coral_fan"},{"id":"minecraft:tuff","localizedName":"Tuff","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff"},{"id":"minecraft:tuff_brick_slab","localizedName":"Tuff Brick Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_slab"},{"id":"minecraft:tuff_brick_stairs","localizedName":"Tuff Brick Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_stairs"},{"id":"minecraft:tuff_brick_wall","localizedName":"Tuff Brick Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_brick_wall"},{"id":"minecraft:tuff_bricks","localizedName":"Tuff Bricks","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_bricks"},{"id":"minecraft:tuff_slab","localizedName":"Tuff Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_slab"},{"id":"minecraft:tuff_stairs","localizedName":"Tuff Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_stairs"},{"id":"minecraft:tuff_wall","localizedName":"Tuff Wall","maxStackSize":64,"unlocalizedName":"block.minecraft.tuff_wall"},{"id":"minecraft:turtle_egg","localizedName":"Turtle Egg","maxStackSize":64,"unlocalizedName":"block.minecraft.turtle_egg"},{"id":"minecraft:turtle_helmet","localizedName":"Turtle Shell","maxDamage":275,"maxStackSize":1,"unlocalizedName":"item.minecraft.turtle_helmet"},{"id":"minecraft:turtle_scute","localizedName":"Turtle Scute","maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_scute"},{"id":"minecraft:turtle_spawn_egg","localizedName":"Turtle Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.turtle_spawn_egg"},{"id":"minecraft:twisting_vines","localizedName":"Twisting Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.twisting_vines"},{"id":"minecraft:vault","localizedName":"Vault","maxStackSize":64,"unlocalizedName":"block.minecraft.vault"},{"id":"minecraft:verdant_froglight","localizedName":"Verdant Froglight","maxStackSize":64,"unlocalizedName":"block.minecraft.verdant_froglight"},{"id":"minecraft:vex_armor_trim_smithing_template","localizedName":"Vex Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.vex_armor_trim_smithing_template"},{"id":"minecraft:vex_spawn_egg","localizedName":"Vex Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.vex_spawn_egg"},{"id":"minecraft:villager_spawn_egg","localizedName":"Villager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.villager_spawn_egg"},{"id":"minecraft:vindicator_spawn_egg","localizedName":"Vindicator Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.vindicator_spawn_egg"},{"id":"minecraft:vine","localizedName":"Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.vine"},{"id":"minecraft:wandering_trader_spawn_egg","localizedName":"Wandering Trader Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wandering_trader_spawn_egg"},{"id":"minecraft:ward_armor_trim_smithing_template","localizedName":"Ward Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.ward_armor_trim_smithing_template"},{"id":"minecraft:warden_spawn_egg","localizedName":"Warden Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.warden_spawn_egg"},{"id":"minecraft:warped_button","localizedName":"Warped Button","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_button"},{"id":"minecraft:warped_door","localizedName":"Warped Door","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_door"},{"id":"minecraft:warped_fence","localizedName":"Warped Fence","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence"},{"id":"minecraft:warped_fence_gate","localizedName":"Warped Fence Gate","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fence_gate"},{"id":"minecraft:warped_fungus","localizedName":"Warped Fungus","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_fungus"},{"id":"minecraft:warped_fungus_on_a_stick","localizedName":"Warped Fungus on a Stick","maxDamage":100,"maxStackSize":1,"unlocalizedName":"item.minecraft.warped_fungus_on_a_stick"},{"id":"minecraft:warped_hanging_sign","localizedName":"Warped Hanging Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.warped_hanging_sign"},{"id":"minecraft:warped_hyphae","localizedName":"Warped Hyphae","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_hyphae"},{"id":"minecraft:warped_nylium","localizedName":"Warped Nylium","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_nylium"},{"id":"minecraft:warped_planks","localizedName":"Warped Planks","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_planks"},{"id":"minecraft:warped_pressure_plate","localizedName":"Warped Pressure Plate","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_pressure_plate"},{"id":"minecraft:warped_roots","localizedName":"Warped Roots","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_roots"},{"id":"minecraft:warped_sign","localizedName":"Warped Sign","maxStackSize":16,"unlocalizedName":"block.minecraft.warped_sign"},{"id":"minecraft:warped_slab","localizedName":"Warped Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_slab"},{"id":"minecraft:warped_stairs","localizedName":"Warped Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stairs"},{"id":"minecraft:warped_stem","localizedName":"Warped Stem","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_stem"},{"id":"minecraft:warped_trapdoor","localizedName":"Warped Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_trapdoor"},{"id":"minecraft:warped_wart_block","localizedName":"Warped Wart Block","maxStackSize":64,"unlocalizedName":"block.minecraft.warped_wart_block"},{"id":"minecraft:water_bucket","localizedName":"Water Bucket","maxStackSize":1,"unlocalizedName":"item.minecraft.water_bucket"},{"id":"minecraft:waxed_chiseled_copper","localizedName":"Waxed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_chiseled_copper"},{"id":"minecraft:waxed_copper_block","localizedName":"Waxed Block of Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_block"},{"id":"minecraft:waxed_copper_bulb","localizedName":"Waxed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_bulb"},{"id":"minecraft:waxed_copper_door","localizedName":"Waxed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_door"},{"id":"minecraft:waxed_copper_grate","localizedName":"Waxed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_grate"},{"id":"minecraft:waxed_copper_trapdoor","localizedName":"Waxed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_copper_trapdoor"},{"id":"minecraft:waxed_cut_copper","localizedName":"Waxed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper"},{"id":"minecraft:waxed_cut_copper_slab","localizedName":"Waxed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_slab"},{"id":"minecraft:waxed_cut_copper_stairs","localizedName":"Waxed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_cut_copper_stairs"},{"id":"minecraft:waxed_exposed_chiseled_copper","localizedName":"Waxed Exposed Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_chiseled_copper"},{"id":"minecraft:waxed_exposed_copper","localizedName":"Waxed Exposed Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper"},{"id":"minecraft:waxed_exposed_copper_bulb","localizedName":"Waxed Exposed Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_bulb"},{"id":"minecraft:waxed_exposed_copper_door","localizedName":"Waxed Exposed Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_door"},{"id":"minecraft:waxed_exposed_copper_grate","localizedName":"Waxed Exposed Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_grate"},{"id":"minecraft:waxed_exposed_copper_trapdoor","localizedName":"Waxed Exposed Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_copper_trapdoor"},{"id":"minecraft:waxed_exposed_cut_copper","localizedName":"Waxed Exposed Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper"},{"id":"minecraft:waxed_exposed_cut_copper_slab","localizedName":"Waxed Exposed Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_slab"},{"id":"minecraft:waxed_exposed_cut_copper_stairs","localizedName":"Waxed Exposed Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_exposed_cut_copper_stairs"},{"id":"minecraft:waxed_oxidized_chiseled_copper","localizedName":"Waxed Oxidized Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_chiseled_copper"},{"id":"minecraft:waxed_oxidized_copper","localizedName":"Waxed Oxidized Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper"},{"id":"minecraft:waxed_oxidized_copper_bulb","localizedName":"Waxed Oxidized Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_bulb"},{"id":"minecraft:waxed_oxidized_copper_door","localizedName":"Waxed Oxidized Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_door"},{"id":"minecraft:waxed_oxidized_copper_grate","localizedName":"Waxed Oxidized Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_grate"},{"id":"minecraft:waxed_oxidized_copper_trapdoor","localizedName":"Waxed Oxidized Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_copper_trapdoor"},{"id":"minecraft:waxed_oxidized_cut_copper","localizedName":"Waxed Oxidized Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper"},{"id":"minecraft:waxed_oxidized_cut_copper_slab","localizedName":"Waxed Oxidized Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_slab"},{"id":"minecraft:waxed_oxidized_cut_copper_stairs","localizedName":"Waxed Oxidized Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_oxidized_cut_copper_stairs"},{"id":"minecraft:waxed_weathered_chiseled_copper","localizedName":"Waxed Weathered Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_chiseled_copper"},{"id":"minecraft:waxed_weathered_copper","localizedName":"Waxed Weathered Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper"},{"id":"minecraft:waxed_weathered_copper_bulb","localizedName":"Waxed Weathered Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_bulb"},{"id":"minecraft:waxed_weathered_copper_door","localizedName":"Waxed Weathered Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_door"},{"id":"minecraft:waxed_weathered_copper_grate","localizedName":"Waxed Weathered Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_grate"},{"id":"minecraft:waxed_weathered_copper_trapdoor","localizedName":"Waxed Weathered Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_copper_trapdoor"},{"id":"minecraft:waxed_weathered_cut_copper","localizedName":"Waxed Weathered Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper"},{"id":"minecraft:waxed_weathered_cut_copper_slab","localizedName":"Waxed Weathered Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_slab"},{"id":"minecraft:waxed_weathered_cut_copper_stairs","localizedName":"Waxed Weathered Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.waxed_weathered_cut_copper_stairs"},{"id":"minecraft:wayfinder_armor_trim_smithing_template","localizedName":"Wayfinder Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.wayfinder_armor_trim_smithing_template"},{"id":"minecraft:weathered_chiseled_copper","localizedName":"Weathered Chiseled Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_chiseled_copper"},{"id":"minecraft:weathered_copper","localizedName":"Weathered Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper"},{"id":"minecraft:weathered_copper_bulb","localizedName":"Weathered Copper Bulb","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_bulb"},{"id":"minecraft:weathered_copper_door","localizedName":"Weathered Copper Door","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_door"},{"id":"minecraft:weathered_copper_grate","localizedName":"Weathered Copper Grate","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_grate"},{"id":"minecraft:weathered_copper_trapdoor","localizedName":"Weathered Copper Trapdoor","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_copper_trapdoor"},{"id":"minecraft:weathered_cut_copper","localizedName":"Weathered Cut Copper","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper"},{"id":"minecraft:weathered_cut_copper_slab","localizedName":"Weathered Cut Copper Slab","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_slab"},{"id":"minecraft:weathered_cut_copper_stairs","localizedName":"Weathered Cut Copper Stairs","maxStackSize":64,"unlocalizedName":"block.minecraft.weathered_cut_copper_stairs"},{"id":"minecraft:weeping_vines","localizedName":"Weeping Vines","maxStackSize":64,"unlocalizedName":"block.minecraft.weeping_vines"},{"id":"minecraft:wet_sponge","localizedName":"Wet Sponge","maxStackSize":64,"unlocalizedName":"block.minecraft.wet_sponge"},{"id":"minecraft:wheat","localizedName":"Wheat","maxStackSize":64,"unlocalizedName":"item.minecraft.wheat"},{"id":"minecraft:wheat_seeds","localizedName":"Wheat Seeds","maxStackSize":64,"unlocalizedName":"item.minecraft.wheat_seeds"},{"id":"minecraft:white_banner","localizedName":"White Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.white_banner"},{"id":"minecraft:white_bed","localizedName":"White Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.white_bed"},{"id":"minecraft:white_bundle","localizedName":"White Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.white_bundle"},{"id":"minecraft:white_candle","localizedName":"White Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.white_candle"},{"id":"minecraft:white_carpet","localizedName":"White Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.white_carpet"},{"id":"minecraft:white_concrete","localizedName":"White Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete"},{"id":"minecraft:white_concrete_powder","localizedName":"White Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.white_concrete_powder"},{"id":"minecraft:white_dye","localizedName":"White Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.white_dye"},{"id":"minecraft:white_glazed_terracotta","localizedName":"White Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.white_glazed_terracotta"},{"id":"minecraft:white_shulker_box","localizedName":"White Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.white_shulker_box"},{"id":"minecraft:white_stained_glass","localizedName":"White Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass"},{"id":"minecraft:white_stained_glass_pane","localizedName":"White Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.white_stained_glass_pane"},{"id":"minecraft:white_terracotta","localizedName":"White Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.white_terracotta"},{"id":"minecraft:white_tulip","localizedName":"White Tulip","maxStackSize":64,"unlocalizedName":"block.minecraft.white_tulip"},{"id":"minecraft:white_wool","localizedName":"White Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.white_wool"},{"id":"minecraft:wild_armor_trim_smithing_template","localizedName":"Wild Armor Trim","maxStackSize":64,"unlocalizedName":"item.minecraft.wild_armor_trim_smithing_template"},{"id":"minecraft:wind_charge","localizedName":"Wind Charge","maxStackSize":64,"unlocalizedName":"item.minecraft.wind_charge"},{"id":"minecraft:witch_spawn_egg","localizedName":"Witch Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.witch_spawn_egg"},{"id":"minecraft:wither_rose","localizedName":"Wither Rose","maxStackSize":64,"unlocalizedName":"block.minecraft.wither_rose"},{"id":"minecraft:wither_skeleton_skull","localizedName":"Wither Skeleton Skull","maxStackSize":64,"unlocalizedName":"block.minecraft.wither_skeleton_skull"},{"id":"minecraft:wither_skeleton_spawn_egg","localizedName":"Wither Skeleton Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wither_skeleton_spawn_egg"},{"id":"minecraft:wither_spawn_egg","localizedName":"Wither Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wither_spawn_egg"},{"id":"minecraft:wolf_armor","localizedName":"Wolf Armor","maxDamage":64,"maxStackSize":1,"unlocalizedName":"item.minecraft.wolf_armor"},{"id":"minecraft:wolf_spawn_egg","localizedName":"Wolf Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.wolf_spawn_egg"},{"id":"minecraft:wooden_axe","localizedName":"Wooden Axe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_axe"},{"id":"minecraft:wooden_hoe","localizedName":"Wooden Hoe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_hoe"},{"id":"minecraft:wooden_pickaxe","localizedName":"Wooden Pickaxe","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_pickaxe"},{"id":"minecraft:wooden_shovel","localizedName":"Wooden Shovel","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_shovel"},{"id":"minecraft:wooden_sword","localizedName":"Wooden Sword","maxDamage":59,"maxStackSize":1,"unlocalizedName":"item.minecraft.wooden_sword"},{"id":"minecraft:writable_book","localizedName":"Book and Quill","maxStackSize":1,"unlocalizedName":"item.minecraft.writable_book"},{"id":"minecraft:written_book","localizedName":"Written Book","maxStackSize":16,"unlocalizedName":"item.minecraft.written_book"},{"id":"minecraft:yellow_banner","localizedName":"Yellow Banner","maxStackSize":16,"unlocalizedName":"block.minecraft.yellow_banner"},{"id":"minecraft:yellow_bed","localizedName":"Yellow Bed","maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_bed"},{"id":"minecraft:yellow_bundle","localizedName":"Yellow Bundle","maxStackSize":1,"unlocalizedName":"item.minecraft.yellow_bundle"},{"id":"minecraft:yellow_candle","localizedName":"Yellow Candle","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_candle"},{"id":"minecraft:yellow_carpet","localizedName":"Yellow Carpet","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_carpet"},{"id":"minecraft:yellow_concrete","localizedName":"Yellow Concrete","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete"},{"id":"minecraft:yellow_concrete_powder","localizedName":"Yellow Concrete Powder","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_concrete_powder"},{"id":"minecraft:yellow_dye","localizedName":"Yellow Dye","maxStackSize":64,"unlocalizedName":"item.minecraft.yellow_dye"},{"id":"minecraft:yellow_glazed_terracotta","localizedName":"Yellow Glazed Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_glazed_terracotta"},{"id":"minecraft:yellow_shulker_box","localizedName":"Yellow Shulker Box","maxStackSize":1,"unlocalizedName":"block.minecraft.yellow_shulker_box"},{"id":"minecraft:yellow_stained_glass","localizedName":"Yellow Stained Glass","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass"},{"id":"minecraft:yellow_stained_glass_pane","localizedName":"Yellow Stained Glass Pane","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_stained_glass_pane"},{"id":"minecraft:yellow_terracotta","localizedName":"Yellow Terracotta","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_terracotta"},{"id":"minecraft:yellow_wool","localizedName":"Yellow Wool","maxStackSize":64,"unlocalizedName":"block.minecraft.yellow_wool"},{"id":"minecraft:zoglin_spawn_egg","localizedName":"Zoglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zoglin_spawn_egg"},{"id":"minecraft:zombie_head","localizedName":"Zombie Head","maxStackSize":64,"unlocalizedName":"block.minecraft.zombie_head"},{"id":"minecraft:zombie_horse_spawn_egg","localizedName":"Zombie Horse Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_horse_spawn_egg"},{"id":"minecraft:zombie_spawn_egg","localizedName":"Zombie Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_spawn_egg"},{"id":"minecraft:zombie_villager_spawn_egg","localizedName":"Zombie Villager Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombie_villager_spawn_egg"},{"id":"minecraft:zombified_piglin_spawn_egg","localizedName":"Zombified Piglin Spawn Egg","maxStackSize":64,"unlocalizedName":"item.minecraft.zombified_piglin_spawn_egg"}] diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 5e922cdae..c3468f9d8 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -54,7 +54,8 @@ "fawe.worldedit.brush.brush.source.mask": "Brush source mask set", "fawe.worldedit.brush.brush.transform.disabled": "Brush transform disabled", "fawe.worldedit.brush.brush.transform": "Brush transform set", - "fawe.worldedit.rollback.rollback.element": "Undoing {0}", + "fawe.worldedit.rollback.rollingback.index": "Undoing {0} ...", + "fawe.worldedit.rollback.rollback.element": "{0} undone.", "fawe.worldedit.tool.tool.inspect": "Inspect tool bound to {0}.", "fawe.worldedit.tool.tool.inspect.info": "{0} changed {1} to {2} {3} ago", "fawe.worldedit.tool.tool.inspect.info.footer": "Total: {0} changes", @@ -67,6 +68,7 @@ "fawe.worldedit.schematic.schematic.loaded": "{0} loaded. Paste it with //paste", "fawe.worldedit.schematic.schematic.saved": "{0} saved.", "fawe.worldedit.schematic.schematic.none": "No files found.", + "fawe.worldedit.schematic.schematic.load-failure": "File could not be read or it does not exist: {0}. If you are specifying a format, you may not be specifying the correct one. Sponge schematic v2 and v3 both use the .schem file extension. To allow FAWE to select the format, do not specify one. If you are using a litematica schematic, it is not supported!", "fawe.worldedit.clipboard.clipboard.uri.not.found": "You do not have {0} loaded", "fawe.worldedit.clipboard.clipboard.cleared": "Clipboard cleared", "fawe.worldedit.clipboard.clipboard.invalid.format": "Unknown clipboard format: {0}", @@ -91,6 +93,7 @@ "fawe.error.parser.invalid-data": "Invalid data: {0}", "fawe.error.unsupported": "Unsupported!", "fawe.error.invalid-block-type": "Does not match a valid block type: {0}", + "fawe.error.invalid-block-state-property": "Cannot parse value `{0}` for property `{1}`, block state: `{2}`", "fawe.error.nbt.forbidden": "You are not allowed to use nbt. Lacking permission: {0}", "fawe.error.invalid-arguments": "Invalid amount of arguments. Expected: {0}", "fawe.error.unrecognised-tag": "Unrecognised tag: {0} {1}", @@ -129,12 +132,16 @@ "fawe.error.parse.no-clipboard-source": "No clipboards found at given source: {0}", "fawe.error.clipboard.invalid": "====== INVALID CLIPBOARD ======", "fawe.error.clipboard.invalid.info": "File: {0} (len: {1})", - "fawe.error.clipboard.load.failure": "Could not load clipboard. Possible that the clipboard is still being written to from another server?!", + "fawe.error.clipboard.load.failure": "Unexpected failure loading clipboard from disk!", "fawe.error.clipboard.on.disk.version.mismatch": "Clipboard version mismatch: expected {0} but got {1}. It is recommended you delete the clipboard folder and restart the server.\nYour clipboard folder is located at {2}.", "fawe.error.limit.disallowed-block": "Your limit disallows use of block '{0}'", "fawe.error.limit.disallowed-property": "Your limit disallows use of property '{0}'", "fawe.error.region-mask-invalid": "Invalid region mask: {0}", "fawe.error.occurred-continuing": "Ignorable error occurred during edit: {0}", + "fawe.error.limit.max-brush-radius": "Maximum brush radius in limit: {0}", + "fawe.error.limit.max-radius": "Maximum radius in limit: {0}", + "fawe.error.no-valid-on-hotbar": "No valid block types on hotbar", + "fawe.error.no-process-non-synchronous-edit": "No processor holder was found but edit is non-synchronous", "fawe.cancel.count": "Cancelled {0} edits.", "fawe.cancel.reason.confirm": "Use //confirm to execute {0}", "fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}", @@ -145,6 +152,7 @@ "fawe.cancel.reason.low.memory": "Low memory", "fawe.cancel.reason.max.changes": "Too many blocks changed", "fawe.cancel.reason.max.checks": "Too many block checks", + "fawe.cancel.reason.max.fails": "Too many fails", "fawe.cancel.reason.max.tiles": "Too many block entities", "fawe.cancel.reason.max.entities": "Too many entities", "fawe.cancel.reason.max.iterations": "Max iterations", @@ -159,6 +167,7 @@ "fawe.cancel.reason.no.region.not.added": "Not added to region", "fawe.cancel.reason.player-only": "This operation requires a player, and cannot be executed from console, or without an actor.", "fawe.cancel.reason.actor-required": "This operation requires an actor.", + "fawe.cancel.reason.world.limit": "This operation cannot be performed at y={0} as it is outside world limits.", "fawe.cancel.worldedit.failed.load.chunk": "Skipped loading chunk: {0};{1}. Try increasing chunk-wait.", "fawe.navigation.no.block": "No block in sight! (or too far)", "fawe.selection.sel.max": "{0} points maximum.", @@ -236,6 +245,7 @@ "worldedit.error.missing-session": "No LocalSession is known", "worldedit.error.missing-world": "You need to provide a world (Try //world)", "worldedit.error.missing-actor": "No actor is known", + "worldedit.error.missing-player": "No player is known", "worldedit.error.no-file-selected": "No file selected.", "worldedit.error.file-resolution.outside-root": "Path is outside allowable root", "worldedit.error.file-resolution.resolve-failed": "Failed to resolve path", @@ -352,9 +362,15 @@ "worldedit.schematic.unknown-format": "Unknown schematic format: {0}.", "worldedit.schematic.load.does-not-exist": "Schematic {0} does not exist!", "worldedit.schematic.load.loading": "(Please wait... loading schematic.)", + "worldedit.schematic.load.unsupported-version": "This schematic is not supported. Version: {0}. If you are using a litematica schematic, it is not supported!", "worldedit.schematic.save.already-exists": "That schematic already exists. Use the -f flag to overwrite it.", "worldedit.schematic.save.failed-directory": "Could not create folder for schematics!", "worldedit.schematic.save.saving": "(Please wait... saving schematic.)", + "worldedit.schematic.save.still-saving": "(Please wait... still saving schematic.)", + "worldedit.schematic.share.unsupported-format": "The schematic share destination \"{0}\" does not support the \"{1}\" format.", + "worldedit.schematic.share.response.arkitektonika.download" : "Download: {0}", + "worldedit.schematic.share.response.arkitektonika.delete" : "Delete: {0}", + "worldedit.schematic.share.response.arkitektonika.click-here" : "[Click here]", "worldedit.schematic.delete.empty": "Schematic {0} not found!", "worldedit.schematic.delete.does-not-exist": "Schematic {0} does not exist!", "worldedit.schematic.delete.failed": "Deletion of {0} failed! Is it read-only?", @@ -462,6 +478,7 @@ "worldedit.curve.convex-only": "//curve only works with convex polyhedral selections", "worldedit.replace.replaced": "{0} blocks have been replaced.", "worldedit.stack.changed": "{0} blocks changed. Undo with //undo", + "worldedit.stack.intersecting-region": "Stack offset must not collide with the region when using block units", "worldedit.regen.regenerated": "Region regenerated.", "worldedit.regen.failed": "Unable to regenerate chunks. Check console for details.", "worldedit.walls.changed": "{0} blocks have been changed.", diff --git a/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java b/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java new file mode 100644 index 000000000..e28d0d236 --- /dev/null +++ b/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java @@ -0,0 +1,136 @@ +package com.fastasyncworldedit.core.queue; + +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class IBatchProcessorTest { + + @Nested + @Isolated + class trimY { + + private static final char[] CHUNK_DATA = new char[16 * 16 * 16]; + private static final char[] SLICE_AIR = new char[16 * 16]; + private static final char[] SLICE_RESERVED = new char[16 * 16]; + private final IBatchProcessor processor = new NoopBatchProcessor(); + + static { + Arrays.fill(CHUNK_DATA, (char) BlockTypesCache.ReservedIDs.AIR); + Arrays.fill(SLICE_AIR, (char) BlockTypesCache.ReservedIDs.AIR); + Arrays.fill(SLICE_RESERVED, (char) BlockTypesCache.ReservedIDs.__RESERVED__); + } + + @ParameterizedTest + @MethodSource("provideTrimYInBoundsParameters") + void testFullChunkSelectedInBoundedRegion(int minY, int maxY, int minSection, int maxSection) { + final IChunkSet set = mock(); + + char[][] sections = new char[(320 + 64) >> 4][CHUNK_DATA.length]; + for (final char[] chars : sections) { + System.arraycopy(CHUNK_DATA, 0, chars, 0, CHUNK_DATA.length); + } + + when(set.getMinSectionPosition()).thenReturn(-64 >> 4); + when(set.getMaxSectionPosition()).thenReturn(319 >> 4); + when(set.hasSection(anyInt())).thenReturn(true); + when(set.loadIfPresent(anyInt())).thenAnswer(invocationOnMock -> sections[invocationOnMock.getArgument(0) + 4]); + doAnswer(invocationOnMock -> { + sections[invocationOnMock.getArgument(0) + 4] = invocationOnMock.getArgument(1); + return null; + }).when(set).setBlocks(anyInt(), any()); + + processor.trimY(set, minY, maxY, true); + + + for (int section = -64 >> 4; section < 320 >> 4; section++) { + int sectionIndex = section + 4; + char[] palette = sections[sectionIndex]; + if (section < minSection) { + assertNull(palette, "expected section below minimum section to be null"); + continue; + } + if (section > maxSection) { + assertNull(palette, "expected section above maximum section to be null"); + continue; + } + if (section == minSection) { + for (int slice = 0; slice < 16; slice++) { + boolean shouldContainBlocks = slice >= (minY % 16); + // If boundaries only span one section, the upper constraints have to be checked explicitly + if (section == maxSection) { + shouldContainBlocks &= slice <= (maxY % 16); + } + assertArrayEquals( + shouldContainBlocks ? SLICE_AIR : SLICE_RESERVED, + Arrays.copyOfRange(palette, slice << 8, (slice + 1) << 8), + ("[lower] slice %d (y=%d) expected to contain " + (shouldContainBlocks ? "air" : "nothing")) + .formatted(slice, ((section << 4) + slice)) + ); + } + continue; + } + if (section == maxSection) { + for (int slice = 0; slice < 16; slice++) { + boolean shouldContainBlocks = slice <= (maxY % 16); + assertArrayEquals( + shouldContainBlocks ? SLICE_AIR : SLICE_RESERVED, + Arrays.copyOfRange(palette, slice << 8, (slice + 1) << 8), + ("[upper] slice %d (y=%d) expected to contain " + (shouldContainBlocks ? "air" : "nothing")) + .formatted(slice, ((section << 4) + slice)) + ); + } + continue; + } + assertArrayEquals(CHUNK_DATA, palette, "full captured chunk @ %d should contain full data".formatted(section)); + } + + } + + /** + * Arguments explained: + * 1. minimum y coordinate (inclusive) + * 2. maximum y coordinate (inclusive) + * 3. chunk section which contains minimum y coordinate + * 4. chunk section which contains maximum y coordinate + */ + private static Stream provideTrimYInBoundsParameters() { + return Stream.of( + Arguments.of(64, 72, 4, 4), + Arguments.of(-64, 0, -4, 0), + Arguments.of(0, 128, 0, 8), + Arguments.of(16, 132, 1, 8), + Arguments.of(4, 144, 0, 9), + Arguments.of(12, 255, 0, 15), + Arguments.of(24, 103, 1, 6) + ); + } + + } + + private static final class NoopBatchProcessor implements IBatchProcessor { + + @Override + public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + return set; + } + + @Override + public @Nullable Extent construct(final Extent child) { + return null; + } + + } + +} diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/BaseExpressionTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/BaseExpressionTest.java index 3491347a4..3c8ba65d6 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/BaseExpressionTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/BaseExpressionTest.java @@ -114,6 +114,11 @@ class BaseExpressionTest { public int getBlockDataRel(double x, double y, double z) { return (int) y * 100; } + + @Override + public ExpressionEnvironment clone() { + return this; + } }); return expression.evaluate(); diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/RealExpressionTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/RealExpressionTest.java index 444e1db9d..a4dd3062a 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/RealExpressionTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/RealExpressionTest.java @@ -74,7 +74,7 @@ class RealExpressionTest extends BaseExpressionTest { Expression compiled = compile(expr, "x", "y", "z"); for (TestCase aCase : cases) { Vector3 loc = aCase.loc; - assertEquals(aCase.result, compiled.evaluate(loc.getX(), loc.getY(), loc.getZ()), 0, + assertEquals(aCase.result, compiled.evaluate(loc.x(), loc.y(), loc.z()), 0, "Test case " + aCase + " failed (result)" ); aCase.postChecks.accept(compiled); diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorterTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorterTest.java index a1582bf04..11057ca25 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorterTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/internal/util/RegionOptimizedVectorSorterTest.java @@ -100,10 +100,10 @@ public class RegionOptimizedVectorSorterTest { for (int i = 0; i < toSort.size() - 1; i++) { BlockVector3 curr = toSort.get(i); BlockVector3 next = toSort.get(i + 1); - int currChunkX = curr.getX() >> 4; - int nextChunkX = next.getX() >> 4; - int currChunkZ = curr.getZ() >> 4; - int nextChunkZ = next.getZ() >> 4; + int currChunkX = curr.x() >> 4; + int nextChunkX = next.x() >> 4; + int currChunkZ = curr.z() >> 4; + int nextChunkZ = next.z() >> 4; int currRegionX = currChunkX >> 5; int nextRegionX = nextChunkX >> 5; int currRegionZ = currChunkZ >> 5; @@ -125,7 +125,7 @@ public class RegionOptimizedVectorSorterTest { fail(spaceship + " " + currChunkZ + " chunk z should be less than or equal to " + nextChunkZ); } else if (currChunkZ == nextChunkZ) { - if (curr.getY() < next.getY()) { + if (curr.y() < next.y()) { fail(spaceship + " " + curr + " y should be greater than or equal to " + next); } diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/util/LocationTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/util/LocationTest.java index 44962055b..2a16b4373 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/util/LocationTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/util/LocationTest.java @@ -65,7 +65,7 @@ public class LocationTest { public void testGetX() throws Exception { World world = mock(World.class); Location location = new Location(world, Vector3.at(TEST_VALUE, 0, 0)); - assertEquals(TEST_VALUE, location.getX(), EPSILON); + assertEquals(TEST_VALUE, location.x(), EPSILON); } @Test @@ -80,17 +80,17 @@ public class LocationTest { World world = mock(World.class); Location location1 = new Location(world, Vector3.ZERO); Location location2 = location1.setX(TEST_VALUE); - assertEquals(0, location1.getX(), EPSILON); - assertEquals(TEST_VALUE, location2.getX(), EPSILON); - assertEquals(0, location2.getY(), EPSILON); - assertEquals(0, location2.getZ(), EPSILON); + assertEquals(0, location1.x(), EPSILON); + assertEquals(TEST_VALUE, location2.x(), EPSILON); + assertEquals(0, location2.y(), EPSILON); + assertEquals(0, location2.z(), EPSILON); } @Test public void testGetY() throws Exception { World world = mock(World.class); Location location = new Location(world, Vector3.at(0, TEST_VALUE, 0)); - assertEquals(TEST_VALUE, location.getY(), EPSILON); + assertEquals(TEST_VALUE, location.y(), EPSILON); } @Test @@ -105,17 +105,17 @@ public class LocationTest { World world = mock(World.class); Location location1 = new Location(world, Vector3.ZERO); Location location2 = location1.setY(TEST_VALUE); - assertEquals(0, location1.getY(), EPSILON); - assertEquals(0, location2.getX(), EPSILON); - assertEquals(TEST_VALUE, location2.getY(), EPSILON); - assertEquals(0, location2.getZ(), EPSILON); + assertEquals(0, location1.y(), EPSILON); + assertEquals(0, location2.x(), EPSILON); + assertEquals(TEST_VALUE, location2.y(), EPSILON); + assertEquals(0, location2.z(), EPSILON); } @Test public void testGetZ() throws Exception { World world = mock(World.class); Location location = new Location(world, Vector3.at(0, 0, TEST_VALUE)); - assertEquals(TEST_VALUE, location.getZ(), EPSILON); + assertEquals(TEST_VALUE, location.z(), EPSILON); } @Test @@ -130,10 +130,10 @@ public class LocationTest { World world = mock(World.class); Location location1 = new Location(world, Vector3.ZERO); Location location2 = location1.setZ(TEST_VALUE); - assertEquals(0, location1.getZ(), EPSILON); - assertEquals(0, location2.getX(), EPSILON); - assertEquals(0, location2.getY(), EPSILON); - assertEquals(TEST_VALUE, location2.getZ(), EPSILON); + assertEquals(0, location1.z(), EPSILON); + assertEquals(0, location2.x(), EPSILON); + assertEquals(0, location2.y(), EPSILON); + assertEquals(TEST_VALUE, location2.z(), EPSILON); } @RepeatedTest(value = 5) @@ -141,7 +141,7 @@ public class LocationTest { World world = mock(World.class); long start = System.currentTimeMillis(); BlockVector3 location1 = BlockVector3.ZERO; - BlockVector3.at(location1.getX() + 10, location1.getY() + 10, location1.getZ() + 10); + BlockVector3.at(location1.x() + 10, location1.y() + 10, location1.z() + 10); System.out.println(System.currentTimeMillis() - start + " ms"); } diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 88f1998b4..9bd557d7d 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -100,7 +100,7 @@ dependencies { } // No need for this at runtime - "modCompileOnly"("me.lucko:fabric-permissions-api:0.1-SNAPSHOT") + "modCompileOnly"("me.lucko:fabric-permissions-api:0.3.3") // Hook these up manually, because Fabric doesn't seem to quite do it properly. "compileOnly"("net.fabricmc:sponge-mixin:${project.versions.mixin}") diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java index cd3c5c313..0d87917d9 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java @@ -126,7 +126,7 @@ public final class NBTConverter { public static net.minecraft.nbt.CompoundTag toNative(CompoundTag tag) { net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag(); - for (Entry child : tag.getValue().entrySet()) { + for (Entry> child : tag.getValue().entrySet()) { compound.put(child.getKey(), toNative(child.getValue())); } return compound; @@ -230,7 +230,7 @@ public final class NBTConverter { public static CompoundTag fromNative(net.minecraft.nbt.CompoundTag other) { Set tags = other.getKeys(); - Map map = new HashMap<>(); + Map> map = new HashMap<>(); for (String tagName : tags) { map.put(tagName, fromNative(other.getTag(tagName))); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java index 9c10a6d30..82ab9ae23 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/NBTConverter.java @@ -139,7 +139,7 @@ public final class NBTConverter { public static CompoundNBT toNative(CompoundTag tag) { CompoundNBT compound = new CompoundNBT(); - for (Entry child : tag.getValue().entrySet()) { + for (Entry> child : tag.getValue().entrySet()) { compound.put(child.getKey(), toNative(child.getValue())); } return compound; @@ -243,7 +243,7 @@ public final class NBTConverter { public static CompoundTag fromNative(CompoundNBT other) { Set tags = other.keySet(); - Map map = new HashMap<>(); + Map> map = new HashMap<>(); for (String tagName : tags) { map.put(tagName, fromNative(other.get(tagName))); } diff --git a/worldedit-libs/core/build.gradle.kts b/worldedit-libs/core/build.gradle.kts index c5eb10887..cace30cd0 100644 --- a/worldedit-libs/core/build.gradle.kts +++ b/worldedit-libs/core/build.gradle.kts @@ -12,5 +12,10 @@ dependencies { "shade"(libs.piston) "shade"(libs.pistonRuntime) "shade"(libs.pistonImpl) - "shade"(libs.adventureNbt) + // Linbus + "shade"(platform(libs.linBus.bom)) + "shade"(libs.linBus.common) + "shade"(libs.linBus.stream) + "shade"(libs.linBus.tree) + "shade"(libs.linBus.format.snbt) } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index aba91acea..356a4d635 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { }) api("org.apache.logging.log4j:log4j-api") api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:5.4.0") + testImplementation("org.mockito:mockito-core:5.14.2") } <<<<<<< HEAD