From 771ffae1489cd182b560f0b54ac3e07251b9ecb5 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sat, 13 Nov 2021 21:54:21 -0800 Subject: [PATCH 01/30] Some 1.18 related version shenaigans Compiles: No --- buildSrc/build.gradle.kts | 4 +-- buildSrc/src/main/kotlin/Versions.kt | 12 ++++----- gradle.properties | 4 +-- worldedit-fabric/build.gradle.kts | 27 +++++++------------ .../main/resources/worldedit.accesswidener | 2 -- 5 files changed, 19 insertions(+), 30 deletions(-) delete mode 100644 worldedit-fabric/src/main/resources/worldedit.accesswidener diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 117672ee3..1b1b5f79a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -45,8 +45,8 @@ implementation(gradleApi()) implementation("gradle.plugin.org.cadixdev.gradle:licenser:0.6.1") implementation("org.ajoberstar.grgit:grgit-gradle:4.1.0") - implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0") - implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.21.0") + implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.0") + implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.24.23") implementation("org.spongepowered:SpongeGradle:0.11.5") implementation("net.minecraftforge.gradle:ForgeGradle:5.1.14") implementation("net.fabricmc:fabric-loom:$loomVersion") diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index ae0ecbc6d..c704bfe73 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -4,12 +4,12 @@ const val TEXT = "3.0.4" const val TEXT_EXTRAS = "3.0.6" const val PISTON = "0.5.7" - const val AUTO_VALUE = "1.7.4" - const val JUNIT = "5.7.0" - const val MOCKITO = "3.7.7" - const val FAST_UTIL = "8.2.1" - const val GUAVA = "21.0" - const val GSON = "2.8.0" + const val AUTO_VALUE = "1.8.2" + const val JUNIT = "5.8.1" + const val MOCKITO = "4.0.0" + const val FAST_UTIL = "8.5.6" + const val GUAVA = "31.0.1-jre" + const val GSON = "2.8.8" } // Properties that need a project reference to resolve: diff --git a/gradle.properties b/gradle.properties index 526b19b3d..9ac9b3f62 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ version=7.2.8-SNAPSHOT org.gradle.jvmargs=-Xmx1512M org.gradle.parallel=true -loom.version=0.8.5 -mixin.version=0.9.2+mixin.0.8.2 +loom.version=0.10.55 +mixin.version=0.10.6+mixin.0.8.4 diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 4a94d746a..7b61f9e86 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -1,5 +1,4 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.task.RemapJarTask buildscript { @@ -21,13 +20,9 @@ apply(plugin = "fabric-loom") apply(plugin = "java-library") -configure { - accessWidener("src/main/resources/worldedit.accesswidener") -} - -val minecraftVersion = "1.17.1" -val yarnMappings = "1.17.1+build.1:v2" -val loaderVersion = "0.11.6" +val minecraftVersion = "1.18-pre1" +val yarnMappings = "1.18-pre1+build.6:v2" +val loaderVersion = "0.12.5" configurations.all { resolutionStrategy { @@ -55,7 +50,7 @@ "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") // [1] declare fabric-api dependency... - "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.36.1+1.17") + "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.42.2+1.18") // [2] Load the API dependencies from the fabric mod json... @Suppress("UNCHECKED_CAST") @@ -110,18 +105,14 @@ "annotationProcessor"("net.fabricmc:fabric-loom:${project.versions.loom}") } -configure { - archivesBaseName = "$archivesBaseName-mc$minecraftVersion" +configure { + archivesName.set("${project.name}-mc$minecraftVersion") } + configure { publications.named("maven") { - artifactId = the().archivesBaseName - artifact(tasks.named("jar")) { - builtBy(tasks.named("remapJar")) - } - artifact(tasks.named("sourcesJar")) { - builtBy(tasks.named("remapSourcesJar")) - } + artifactId = the().archivesName.get() + from(components["java"]) } } diff --git a/worldedit-fabric/src/main/resources/worldedit.accesswidener b/worldedit-fabric/src/main/resources/worldedit.accesswidener deleted file mode 100644 index 027fe2d27..000000000 --- a/worldedit-fabric/src/main/resources/worldedit.accesswidener +++ /dev/null @@ -1,2 +0,0 @@ -accessWidener v1 named -accessible class net/minecraft/server/world/ServerChunkManager$MainThreadExecutor From 410688e7b7aa0e87ddc3ec63fe4b17976de04d21 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 14 Nov 2021 00:01:06 -0800 Subject: [PATCH 02/30] [Fabric] Update to 1.18-pre1, Mojmapped Also Gradle 7.3. :) --- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 4 +- buildSrc/src/main/kotlin/LibsConfig.kt | 1 + buildSrc/src/main/kotlin/PlatformConfig.kt | 3 +- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 269 +++++--- worldedit-fabric/build.gradle.kts | 25 +- .../worldedit/fabric/CommandWrapper.java | 28 +- .../sk89q/worldedit/fabric/FabricAdapter.java | 93 ++- .../worldedit/fabric/FabricBiomeRegistry.java | 6 +- .../fabric/FabricBlockCategoryRegistry.java | 11 +- .../worldedit/fabric/FabricBlockMaterial.java | 19 +- .../worldedit/fabric/FabricBlockRegistry.java | 19 +- .../worldedit/fabric/FabricDataFixer.java | 640 +++++++++--------- .../sk89q/worldedit/fabric/FabricEntity.java | 37 +- .../fabric/FabricEntityProperties.java | 76 +-- .../fabric/FabricItemCategoryRegistry.java | 11 +- .../worldedit/fabric/FabricItemRegistry.java | 4 +- .../fabric/FabricPermissionsProvider.java | 14 +- .../worldedit/fabric/FabricPlatform.java | 49 +- .../sk89q/worldedit/fabric/FabricPlayer.java | 99 ++- .../sk89q/worldedit/fabric/FabricWorld.java | 369 +++++----- .../worldedit/fabric/FabricWorldEdit.java | 98 +-- .../worldedit/fabric/MutableBiomeArray.java | 42 -- .../worldedit/fabric/ThreadSafeCache.java | 7 +- .../worldedit/fabric/WorldEditFakePlayer.java | 23 +- .../fabric/WorldEditGenListener.java | 13 +- .../fabric/internal/ExtendedChunk.java | 9 +- .../internal/ExtendedMinecraftServer.java | 9 +- .../fabric/internal/FabricTransmogrifier.java | 61 +- .../internal/FabricWorldNativeAccess.java | 79 ++- .../fabric/internal/MixinConfigPlugin.java | 2 +- .../fabric/internal/NBTConverter.java | 152 ++--- .../fabric/internal/PropertyAdapter.java | 8 +- .../AccessorClientSettingsC2SPacket.java | 32 - ...essorClientboundBlockEntityDataPacket.java | 16 + ...ies.java => AccessorPrimaryLevelData.java} | 12 +- ...ger.java => AccessorServerChunkCache.java} | 17 +- .../fabric/mixin/MixinBiomeArray.java | 49 -- ....java => MixinLevelChunkSetBlockHook.java} | 36 +- .../fabric/mixin/MixinMinecraftServer.java | 22 +- ...ayerEntity.java => MixinServerPlayer.java} | 14 +- .../net/handler/WECUIPacketHandler.java | 5 +- .../main/resources/worldedit.accesswidener | 2 + .../src/main/resources/worldedit.mixins.json | 11 +- worldedit-forge/build.gradle.kts | 2 +- 46 files changed, 1210 insertions(+), 1290 deletions(-) delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/MutableBiomeArray.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientSettingsC2SPacket.java create mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/{AccessorLevelProperties.java => AccessorPrimaryLevelData.java} (76%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/{AccessorServerChunkManager.java => AccessorServerChunkCache.java} (66%) delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinBiomeArray.java rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/{MixinWorldChunkSetBlockHook.java => MixinLevelChunkSetBlockHook.java} (58%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/{MixinServerPlayerEntity.java => MixinServerPlayer.java} (72%) create mode 100644 worldedit-fabric/src/main/resources/worldedit.accesswidener diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 01a57b104..c4b652888 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -11,7 +11,7 @@ import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.withType -fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean = true) { +fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, javaRelease: Int = 8, banSlf4j: Boolean = true) { applyCommonConfiguration() apply(plugin = "eclipse") apply(plugin = "idea") @@ -24,7 +24,7 @@ val disabledLint = listOf( "processing", "path", "fallthrough", "serial" ) - options.release.set(8) + options.release.set(javaRelease) options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) options.isDeprecation = true options.encoding = "UTF-8" diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 0fd2d6253..5a422a4d8 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -47,6 +47,7 @@ dependencies { exclude(dependency("com.google.guava:guava")) exclude(dependency("com.google.code.gson:gson")) + exclude(dependency("com.google.errorprone:error_prone_annotations")) exclude(dependency("org.checkerframework:checker-qual")) exclude(dependency("org.apache.logging.log4j:log4j-api")) exclude(dependency("com.google.code.findbugs:jsr305")) diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt index a439a2ebf..760ad90d2 100644 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ b/buildSrc/src/main/kotlin/PlatformConfig.kt @@ -11,13 +11,14 @@ import org.gradle.kotlin.dsl.register import kotlin.collections.set -fun Project.applyPlatformAndCoreConfiguration() { +fun Project.applyPlatformAndCoreConfiguration(javaRelease: Int = 8) { applyCommonConfiguration() apply(plugin = "java") apply(plugin = "maven-publish") apply(plugin = "com.jfrog.artifactory") applyCommonJavaConfiguration( sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit", "worldedit-fabric"), + javaRelease = javaRelease, banSlf4j = name !in setOf("worldedit-fabric", "worldedit-forge"), ) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 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 B8dv}T delta 17845 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 X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc3c..e750102e0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c8..1b6c78733 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # 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"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 7b61f9e86..060115fc9 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -1,4 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import net.fabricmc.loom.api.LoomGradleExtensionAPI import net.fabricmc.loom.task.RemapJarTask buildscript { @@ -14,7 +15,7 @@ } } -applyPlatformAndCoreConfiguration() +applyPlatformAndCoreConfiguration(javaRelease = 16) applyShadowConfiguration() apply(plugin = "fabric-loom") @@ -24,14 +25,12 @@ val yarnMappings = "1.18-pre1+build.6:v2" val loaderVersion = "0.12.5" -configurations.all { - resolutionStrategy { - force("com.google.guava:guava:21.0") - } -} - val fabricApiConfiguration: Configuration = configurations.create("fabricApi") +configure { + accessWidenerPath.set(project.file("src/main/resources/worldedit.accesswidener")) +} + repositories { maven { name = "Fabric" @@ -46,7 +45,7 @@ }) "minecraft"("com.mojang:minecraft:$minecraftVersion") - "mappings"("net.fabricmc:yarn:$yarnMappings") + "mappings"(project.the().officialMojangMappings()) "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") // [1] declare fabric-api dependency... @@ -103,6 +102,9 @@ "compileOnly"("net.fabricmc:sponge-mixin:${project.versions.mixin}") "annotationProcessor"("net.fabricmc:sponge-mixin:${project.versions.mixin}") "annotationProcessor"("net.fabricmc:fabric-loom:${project.versions.loom}") + + // Silence some warnings, since apparently this isn't on the compile classpath like it should be. + "compileOnly"("com.google.errorprone:error_prone_annotations:2.10.0") } configure { @@ -147,10 +149,3 @@ tasks.named("assemble").configure { dependsOn("remapShadowJar") } - -configure { - publications.named("maven") { - // Remove when https://github.com/gradle/gradle/issues/16555 is fixed - suppressPomMetadataWarningsFor("runtimeElements") - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java index 8590093a6..ebdd2f68a 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java @@ -34,9 +34,6 @@ import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.util.Substring; -import net.minecraft.entity.Entity; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.MapBackedValueStore; @@ -45,10 +42,13 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer; -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; +import static net.minecraft.commands.Commands.argument; +import static net.minecraft.commands.Commands.literal; public final class CommandWrapper { @@ -56,20 +56,20 @@ public final class CommandWrapper { private CommandWrapper() { } - public static void register(CommandDispatcher dispatcher, org.enginehub.piston.Command command) { + public static void register(CommandDispatcher dispatcher, org.enginehub.piston.Command command) { ImmutableList.Builder aliases = ImmutableList.builder(); aliases.add(command.getName()).addAll(command.getAliases()); - Command commandRunner = ctx -> { + Command commandRunner = ctx -> { WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent( - adaptPlayer(ctx.getSource().getPlayer()), + adaptPlayer(ctx.getSource().getPlayerOrException()), ctx.getInput() )); return 0; }; for (String alias : aliases.build()) { - LiteralArgumentBuilder base = literal(alias).executes(commandRunner) + LiteralArgumentBuilder base = literal(alias).executes(commandRunner) .then(argument("args", StringArgumentType.greedyString()) .suggests(CommandWrapper::suggest) .executes(commandRunner)); @@ -80,23 +80,23 @@ public static void register(CommandDispatcher dispatcher, o } } - private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { + private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { return ctx -> { final Entity entity = ctx.getEntity(); - if (!(entity instanceof ServerPlayerEntity)) { + if (!(entity instanceof ServerPlayer)) { return true; } - final Actor actor = FabricAdapter.adaptPlayer(((ServerPlayerEntity) entity)); + final Actor actor = FabricAdapter.adaptPlayer(((ServerPlayer) entity)); InjectedValueStore store = MapBackedValueStore.create(); store.injectValue(Key.of(Actor.class), context -> Optional.of(actor)); return mapping.getCondition().satisfied(store); }; } - private static CompletableFuture suggest(CommandContext context, + private static CompletableFuture suggest(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { CommandSuggestionEvent event = new CommandSuggestionEvent( - FabricAdapter.adaptPlayer(context.getSource().getPlayer()), + FabricAdapter.adaptPlayer(context.getSource().getPlayerOrException()), builder.getInput() ); WorldEdit.getInstance().getEventBus().post(event); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java index fb30fb2c5..c6d6edb6c 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java @@ -37,23 +37,22 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.util.Identifier; -import net.minecraft.util.StringIdentifiable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.Biome; - import java.util.Comparator; import java.util.Map; import java.util.Objects; import java.util.TreeMap; import javax.annotation.Nullable; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.Item; +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.state.properties.DirectionProperty; +import net.minecraft.world.phys.Vec3; import static com.google.common.base.Preconditions.checkNotNull; @@ -62,7 +61,7 @@ public final class FabricAdapter { private FabricAdapter() { } - public static World adapt(net.minecraft.world.World world) { + public static World adapt(net.minecraft.world.level.Level world) { return new FabricWorld(world); } @@ -72,7 +71,7 @@ public static World adapt(net.minecraft.world.World world) { * @param world the WorldEdit world * @return a Fabric world */ - public static net.minecraft.world.World adapt(World world) { + public static net.minecraft.world.level.Level adapt(World world) { checkNotNull(world); if (world instanceof FabricWorld) { return ((FabricWorld) world).getWorld(); @@ -84,19 +83,19 @@ public static net.minecraft.world.World adapt(World world) { public static Biome adapt(BiomeType biomeType) { return FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow() - .getRegistryManager() - .get(Registry.BIOME_KEY) - .get(new Identifier(biomeType.getId())); + .registryAccess() + .registryOrThrow(Registry.BIOME_REGISTRY) + .get(new ResourceLocation(biomeType.getId())); } public static BiomeType adapt(Biome biome) { - Identifier id = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getRegistryManager() - .get(Registry.BIOME_KEY).getId(biome); + ResourceLocation id = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().registryAccess() + .registryOrThrow(Registry.BIOME_REGISTRY).getKey(biome); Objects.requireNonNull(id, "biome is not registered"); return BiomeTypes.get(id.toString()); } - public static Vector3 adapt(Vec3d vector) { + public static Vector3 adapt(Vec3 vector) { return Vector3.at(vector.x, vector.y, vector.z); } @@ -104,24 +103,24 @@ public static BlockVector3 adapt(BlockPos pos) { return BlockVector3.at(pos.getX(), pos.getY(), pos.getZ()); } - public static Vec3d toVec3(BlockVector3 vector) { - return new Vec3d(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + public static Vec3 toVec3(BlockVector3 vector) { + return new Vec3(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); } - public static net.minecraft.util.math.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { switch (face) { - case NORTH: return net.minecraft.util.math.Direction.NORTH; - case SOUTH: return net.minecraft.util.math.Direction.SOUTH; - case WEST: return net.minecraft.util.math.Direction.WEST; - case EAST: return net.minecraft.util.math.Direction.EAST; - case DOWN: return net.minecraft.util.math.Direction.DOWN; + 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.util.math.Direction.UP; + return net.minecraft.core.Direction.UP; } } - public static Direction adaptEnumFacing(@Nullable net.minecraft.util.math.Direction face) { + public static Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction face) { if (face == null) { return null; } @@ -146,7 +145,7 @@ public static BlockPos toBlockPos(BlockVector3 vector) { * @deprecated without replacement, use the block adapter methods */ @Deprecated - public static Property adaptProperty(net.minecraft.state.property.Property property) { + public static Property adaptProperty(net.minecraft.world.level.block.state.properties.Property property) { return FabricTransmogrifier.transmogToWorldEditProperty(property); } @@ -155,30 +154,30 @@ public static Property adaptProperty(net.minecraft.state.property.Property * @deprecated without replacement, use the block adapter methods */ @Deprecated - public static Map, Object> adaptProperties(BlockType block, Map, Comparable> mcProps) { + public static Map, Object> adaptProperties(BlockType block, Map, Comparable> mcProps) { Map, Object> props = new TreeMap<>(Comparator.comparing(Property::getName)); - for (Map.Entry, Comparable> prop : mcProps.entrySet()) { + for (Map.Entry, Comparable> prop : mcProps.entrySet()) { Object value = prop.getValue(); if (prop.getKey() instanceof DirectionProperty) { - value = adaptEnumFacing((net.minecraft.util.math.Direction) value); - } else if (prop.getKey() instanceof net.minecraft.state.property.EnumProperty) { - value = ((StringIdentifiable) value).asString(); + value = adaptEnumFacing((net.minecraft.core.Direction) value); + } else if (prop.getKey() instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + value = ((StringRepresentable) value).getSerializedName(); } props.put(block.getProperty(prop.getKey().getName()), value); } return props; } - public static net.minecraft.block.BlockState adapt(BlockState blockState) { + public static net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) { int blockStateId = BlockStateIdAccess.getBlockStateId(blockState); if (!BlockStateIdAccess.isValidInternalId(blockStateId)) { return FabricTransmogrifier.transmogToMinecraft(blockState); } - return Block.getStateFromRawId(blockStateId); + return Block.stateById(blockStateId); } - public static BlockState adapt(net.minecraft.block.BlockState blockState) { - int blockStateId = Block.getRawIdFromState(blockState); + public static BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + int blockStateId = Block.getId(blockState); BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId); if (worldEdit == null) { return FabricTransmogrifier.transmogToWorldEdit(blockState); @@ -187,23 +186,23 @@ public static BlockState adapt(net.minecraft.block.BlockState blockState) { } public static Block adapt(BlockType blockType) { - return Registry.BLOCK.get(new Identifier(blockType.getId())); + return Registry.BLOCK.get(new ResourceLocation(blockType.getId())); } public static BlockType adapt(Block block) { - return BlockTypes.get(Registry.BLOCK.getId(block).toString()); + return BlockTypes.get(Registry.BLOCK.getKey(block).toString()); } public static Item adapt(ItemType itemType) { - return Registry.ITEM.get(new Identifier(itemType.getId())); + return Registry.ITEM.get(new ResourceLocation(itemType.getId())); } public static ItemType adapt(Item item) { - return ItemTypes.get(Registry.ITEM.getId(item).toString()); + return ItemTypes.get(Registry.ITEM.getKey(item).toString()); } public static ItemStack adapt(BaseItemStack baseItemStack) { - net.minecraft.nbt.NbtCompound fabricCompound = null; + net.minecraft.nbt.CompoundTag fabricCompound = null; if (baseItemStack.getNbtData() != null) { fabricCompound = NBTConverter.toNative(baseItemStack.getNbtData()); } @@ -213,7 +212,7 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { } public static BaseItemStack adapt(ItemStack itemStack) { - CompoundTag tag = NBTConverter.fromNative(itemStack.writeNbt(new net.minecraft.nbt.NbtCompound())); + CompoundTag tag = NBTConverter.fromNative(itemStack.save(new net.minecraft.nbt.CompoundTag())); if (tag.getValue().isEmpty()) { tag = null; } else { @@ -233,7 +232,7 @@ public static BaseItemStack adapt(ItemStack itemStack) { * @param player the player * @return the WorldEdit player */ - public static FabricPlayer adaptPlayer(ServerPlayerEntity player) { + public static FabricPlayer adaptPlayer(ServerPlayer player) { checkNotNull(player); return new FabricPlayer(player); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java index d78b95bd5..d2e3b1b16 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java @@ -24,8 +24,8 @@ import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.registry.BiomeRegistry; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; +import net.minecraft.Util; +import net.minecraft.resources.ResourceLocation; /** * Provides access to biome data in Fabric. @@ -34,7 +34,7 @@ class FabricBiomeRegistry implements BiomeRegistry { @Override public Component getRichName(BiomeType biomeType) { - return TranslatableComponent.of(Util.createTranslationKey("biome", new Identifier(biomeType.getId()))); + return TranslatableComponent.of(Util.makeDescriptionId("biome", new ResourceLocation(biomeType.getId()))); } @Deprecated diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java index 1d5d1b185..39dddea16 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java @@ -21,20 +21,19 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; -import net.minecraft.tag.BlockTags; -import net.minecraft.tag.Tag; -import net.minecraft.util.Identifier; - import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.Tag; public class FabricBlockCategoryRegistry implements BlockCategoryRegistry { @Override public Set getCategorisedByName(String category) { - return Optional.ofNullable(BlockTags.getTagGroup().getTag(new Identifier(category))) - .map(Tag::values) + return Optional.ofNullable(BlockTags.getAllTags().getTag(new ResourceLocation(category))) + .map(Tag::getValues) .orElse(Collections.emptyList()) .stream() .map(FabricAdapter::adapt) diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java index ae420c10f..b4fa668f7 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java @@ -21,11 +21,10 @@ import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.PassthroughBlockMaterial; -import net.minecraft.block.BlockState; -import net.minecraft.block.Material; -import net.minecraft.block.piston.PistonBehavior; - import javax.annotation.Nullable; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.PushReaction; /** * Fabric block material that pulls as much info as possible from the Minecraft @@ -50,7 +49,7 @@ public boolean isAir() { @Override public boolean isOpaque() { - return delegate.blocksLight(); + return delegate.isSolidBlocking(); } @Override @@ -65,27 +64,27 @@ public boolean isSolid() { @Override public boolean isFragileWhenPushed() { - return delegate.getPistonBehavior() == PistonBehavior.DESTROY; + return delegate.getPushReaction() == PushReaction.DESTROY; } @Override public boolean isUnpushable() { - return delegate.getPistonBehavior() == PistonBehavior.BLOCK; + return delegate.getPushReaction() == PushReaction.BLOCK; } @Override public boolean isMovementBlocker() { - return delegate.blocksMovement(); + return delegate.blocksMotion(); } @Override public boolean isBurnable() { - return delegate.isBurnable(); + return delegate.isFlammable(); } @Override public boolean isToolRequired() { - return block.isToolRequired(); + return block.requiresCorrectToolForDrops(); } @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java index ef28a94cc..cd6a771ea 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java @@ -27,28 +27,27 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.BundledBlockRegistry; -import net.minecraft.block.Block; - import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.OptionalInt; import java.util.TreeMap; +import net.minecraft.world.level.block.Block; public class FabricBlockRegistry extends BundledBlockRegistry { - private final Map materialMap = new HashMap<>(); + private final Map materialMap = new HashMap<>(); @Override public Component getRichName(BlockType blockType) { - return TranslatableComponent.of(FabricAdapter.adapt(blockType).getTranslationKey()); + return TranslatableComponent.of(FabricAdapter.adapt(blockType).getDescriptionId()); } @Override public BlockMaterial getMaterial(BlockType blockType) { Block block = FabricAdapter.adapt(blockType); return materialMap.computeIfAbsent( - block.getDefaultState(), + block.defaultBlockState(), m -> new FabricBlockMaterial(m.getMaterial(), m, super.getMaterial(blockType)) ); } @@ -57,10 +56,10 @@ public BlockMaterial getMaterial(BlockType blockType) { public Map> getProperties(BlockType blockType) { Block block = FabricAdapter.adapt(blockType); Map> map = new TreeMap<>(); - Collection> propertyKeys = block - .getDefaultState() + Collection> propertyKeys = block + .defaultBlockState() .getProperties(); - for (net.minecraft.state.property.Property key : propertyKeys) { + for (net.minecraft.world.level.block.state.properties.Property key : propertyKeys) { map.put(key.getName(), FabricTransmogrifier.transmogToWorldEditProperty(key)); } return map; @@ -68,7 +67,7 @@ public BlockMaterial getMaterial(BlockType blockType) { @Override public OptionalInt getInternalBlockStateId(BlockState state) { - net.minecraft.block.BlockState equivalent = FabricAdapter.adapt(state); - return OptionalInt.of(Block.getRawIdFromState(equivalent)); + net.minecraft.world.level.block.state.BlockState equivalent = FabricAdapter.adapt(state); + return OptionalInt.of(Block.getId(equivalent)); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java index bcc445f98..f58c02a95 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java @@ -37,20 +37,20 @@ import com.mojang.serialization.Dynamic; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.fabric.internal.NBTConverter; -import net.minecraft.datafixer.Schemas; -import net.minecraft.datafixer.TypeReferences; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtFloat; -import net.minecraft.nbt.NbtList; +import net.minecraft.core.Direction; +import net.minecraft.nbt.FloatTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.NbtString; -import net.minecraft.text.LiteralText; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.math.Direction; +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.network.chat.TextComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +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; @@ -108,50 +108,50 @@ public T fixUp(FixType type, T original, int srcVer) { } private CompoundTag fixChunk(CompoundTag originalChunk, int srcVer) { - net.minecraft.nbt.NbtCompound tag = NBTConverter.toNative(originalChunk); - net.minecraft.nbt.NbtCompound fixed = convert(LegacyType.CHUNK, tag, srcVer); + net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(originalChunk); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); return NBTConverter.fromNative(fixed); } private CompoundTag fixBlockEntity(CompoundTag origTileEnt, int srcVer) { - net.minecraft.nbt.NbtCompound tag = NBTConverter.toNative(origTileEnt); - net.minecraft.nbt.NbtCompound fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); + net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origTileEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); } private CompoundTag fixEntity(CompoundTag origEnt, int srcVer) { - net.minecraft.nbt.NbtCompound tag = NBTConverter.toNative(origEnt); - net.minecraft.nbt.NbtCompound fixed = convert(LegacyType.ENTITY, tag, srcVer); + net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); return NBTConverter.fromNative(fixed); } private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.NbtCompound stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.NbtCompound fixed = (net.minecraft.nbt.NbtCompound) INSTANCE.fixer.update(TypeReferences.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); + 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.NbtCompound tagCompound) { + 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.NbtCompound props = tagCompound.getCompound("Properties"); - sb.append(props.getKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(","))); + 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.NbtCompound stateToNBT(String blockState) { + private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { int propIdx = blockState.indexOf('['); - net.minecraft.nbt.NbtCompound tag = new net.minecraft.nbt.NbtCompound(); + 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.NbtCompound propTag = new net.minecraft.nbt.NbtCompound(); + 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) { @@ -164,15 +164,15 @@ private static net.minecraft.nbt.NbtCompound stateToNBT(String blockState) { } private String fixBiome(String key, int srcVer) { - return fixName(key, srcVer, TypeReferences.BIOME); + return fixName(key, srcVer, References.BIOME); } private String fixItemType(String key, int srcVer) { - return fixName(key, srcVer, TypeReferences.ITEM_NAME); + 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, NbtString.of(key)), srcVer, DATA_VERSION) + return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, DATA_VERSION) .asString().result().orElse(key); } @@ -189,14 +189,14 @@ private static String fixName(String key, int srcVer, TypeReference type) { private static final Map DFU_TO_LEGACY = new HashMap<>(); public enum LegacyType { - LEVEL(TypeReferences.LEVEL), - PLAYER(TypeReferences.PLAYER), - CHUNK(TypeReferences.CHUNK), - BLOCK_ENTITY(TypeReferences.BLOCK_ENTITY), - ENTITY(TypeReferences.ENTITY), - ITEM_INSTANCE(TypeReferences.ITEM_STACK), - OPTIONS(TypeReferences.OPTIONS), - STRUCTURE(TypeReferences.STRUCTURE); + 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; @@ -216,7 +216,7 @@ public TypeReference getDFUType() { INSTANCE = this; registerConverters(); registerInspectors(); - this.fixer = new WrappedDataFixer(Schemas.getFixer()); + this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); } @Override @@ -235,7 +235,7 @@ private class WrappedDataFixer implements DataFixer { 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.NbtCompound cmp = (net.minecraft.nbt.NbtCompound) dynamic.getValue(); + net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); int desiredVersion = Math.min(targetVer, LEGACY_VERSION); cmp = convert(legacyType, cmp, sourceVer, desiredVersion); @@ -245,7 +245,7 @@ public Dynamic update(TypeReference type, Dynamic dynamic, int sourceV return realFixer.update(type, dynamic, sourceVer, targetVer); } - private net.minecraft.nbt.NbtCompound convert(LegacyType type, net.minecraft.nbt.NbtCompound cmp, int sourceVer, int desiredVersion) { + private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int desiredVersion) { List converters = FabricDataFixer.this.converters.get(type); if (converters != null && !converters.isEmpty()) { for (DataConverter converter : converters) { @@ -272,44 +272,44 @@ public Schema getSchema(int i) { } } - public static net.minecraft.nbt.NbtCompound convert(LegacyType type, net.minecraft.nbt.NbtCompound cmp) { + public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { return convert(type.getDFUType(), cmp); } - public static net.minecraft.nbt.NbtCompound convert(LegacyType type, net.minecraft.nbt.NbtCompound cmp, int sourceVer) { + 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.NbtCompound convert(LegacyType type, net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + 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.NbtCompound convert(TypeReference type, net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound convert(TypeReference type, net.minecraft.nbt.NbtCompound cmp, int sourceVer) { + 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.NbtCompound convert(TypeReference type, net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + 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.NbtCompound) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); + return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); } public interface DataInspector { - net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer); + net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); } public interface DataConverter { int getDataVersion(); - net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp); + net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); } @@ -465,141 +465,141 @@ private void registerEntityItemListEquipment(String type) { registerEntityItemList(type, "ArmorItems", "HandItems"); } - private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); + private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); static { - final Map map = OLD_ID_TO_KEY_MAP; - map.put("EntityItem", new Identifier("item")); - map.put("EntityExperienceOrb", new Identifier("xp_orb")); - map.put("EntityAreaEffectCloud", new Identifier("area_effect_cloud")); - map.put("EntityGuardianElder", new Identifier("elder_guardian")); - map.put("EntitySkeletonWither", new Identifier("wither_skeleton")); - map.put("EntitySkeletonStray", new Identifier("stray")); - map.put("EntityEgg", new Identifier("egg")); - map.put("EntityLeash", new Identifier("leash_knot")); - map.put("EntityPainting", new Identifier("painting")); - map.put("EntityTippedArrow", new Identifier("arrow")); - map.put("EntitySnowball", new Identifier("snowball")); - map.put("EntityLargeFireball", new Identifier("fireball")); - map.put("EntitySmallFireball", new Identifier("small_fireball")); - map.put("EntityEnderPearl", new Identifier("ender_pearl")); - map.put("EntityEnderSignal", new Identifier("eye_of_ender_signal")); - map.put("EntityPotion", new Identifier("potion")); - map.put("EntityThrownExpBottle", new Identifier("xp_bottle")); - map.put("EntityItemFrame", new Identifier("item_frame")); - map.put("EntityWitherSkull", new Identifier("wither_skull")); - map.put("EntityTNTPrimed", new Identifier("tnt")); - map.put("EntityFallingBlock", new Identifier("falling_block")); - map.put("EntityFireworks", new Identifier("fireworks_rocket")); - map.put("EntityZombieHusk", new Identifier("husk")); - map.put("EntitySpectralArrow", new Identifier("spectral_arrow")); - map.put("EntityShulkerBullet", new Identifier("shulker_bullet")); - map.put("EntityDragonFireball", new Identifier("dragon_fireball")); - map.put("EntityZombieVillager", new Identifier("zombie_villager")); - map.put("EntityHorseSkeleton", new Identifier("skeleton_horse")); - map.put("EntityHorseZombie", new Identifier("zombie_horse")); - map.put("EntityArmorStand", new Identifier("armor_stand")); - map.put("EntityHorseDonkey", new Identifier("donkey")); - map.put("EntityHorseMule", new Identifier("mule")); - map.put("EntityEvokerFangs", new Identifier("evocation_fangs")); - map.put("EntityEvoker", new Identifier("evocation_illager")); - map.put("EntityVex", new Identifier("vex")); - map.put("EntityVindicator", new Identifier("vindication_illager")); - map.put("EntityIllagerIllusioner", new Identifier("illusion_illager")); - map.put("EntityMinecartCommandBlock", new Identifier("commandblock_minecart")); - map.put("EntityBoat", new Identifier("boat")); - map.put("EntityMinecartRideable", new Identifier("minecart")); - map.put("EntityMinecartChest", new Identifier("chest_minecart")); - map.put("EntityMinecartFurnace", new Identifier("furnace_minecart")); - map.put("EntityMinecartTNT", new Identifier("tnt_minecart")); - map.put("EntityMinecartHopper", new Identifier("hopper_minecart")); - map.put("EntityMinecartMobSpawner", new Identifier("spawner_minecart")); - map.put("EntityCreeper", new Identifier("creeper")); - map.put("EntitySkeleton", new Identifier("skeleton")); - map.put("EntitySpider", new Identifier("spider")); - map.put("EntityGiantZombie", new Identifier("giant")); - map.put("EntityZombie", new Identifier("zombie")); - map.put("EntitySlime", new Identifier("slime")); - map.put("EntityGhast", new Identifier("ghast")); - map.put("EntityPigZombie", new Identifier("zombie_pigman")); - map.put("EntityEnderman", new Identifier("enderman")); - map.put("EntityCaveSpider", new Identifier("cave_spider")); - map.put("EntitySilverfish", new Identifier("silverfish")); - map.put("EntityBlaze", new Identifier("blaze")); - map.put("EntityMagmaCube", new Identifier("magma_cube")); - map.put("EntityEnderDragon", new Identifier("ender_dragon")); - map.put("EntityWither", new Identifier("wither")); - map.put("EntityBat", new Identifier("bat")); - map.put("EntityWitch", new Identifier("witch")); - map.put("EntityEndermite", new Identifier("endermite")); - map.put("EntityGuardian", new Identifier("guardian")); - map.put("EntityShulker", new Identifier("shulker")); - map.put("EntityPig", new Identifier("pig")); - map.put("EntitySheep", new Identifier("sheep")); - map.put("EntityCow", new Identifier("cow")); - map.put("EntityChicken", new Identifier("chicken")); - map.put("EntitySquid", new Identifier("squid")); - map.put("EntityWolf", new Identifier("wolf")); - map.put("EntityMushroomCow", new Identifier("mooshroom")); - map.put("EntitySnowman", new Identifier("snowman")); - map.put("EntityOcelot", new Identifier("ocelot")); - map.put("EntityIronGolem", new Identifier("villager_golem")); - map.put("EntityHorse", new Identifier("horse")); - map.put("EntityRabbit", new Identifier("rabbit")); - map.put("EntityPolarBear", new Identifier("polar_bear")); - map.put("EntityLlama", new Identifier("llama")); - map.put("EntityLlamaSpit", new Identifier("llama_spit")); - map.put("EntityParrot", new Identifier("parrot")); - map.put("EntityVillager", new Identifier("villager")); - map.put("EntityEnderCrystal", new Identifier("ender_crystal")); - map.put("TileEntityFurnace", new Identifier("furnace")); - map.put("TileEntityChest", new Identifier("chest")); - map.put("TileEntityEnderChest", new Identifier("ender_chest")); - map.put("TileEntityRecordPlayer", new Identifier("jukebox")); - map.put("TileEntityDispenser", new Identifier("dispenser")); - map.put("TileEntityDropper", new Identifier("dropper")); - map.put("TileEntitySign", new Identifier("sign")); - map.put("TileEntityMobSpawner", new Identifier("mob_spawner")); - map.put("TileEntityNote", new Identifier("noteblock")); - map.put("TileEntityPiston", new Identifier("piston")); - map.put("TileEntityBrewingStand", new Identifier("brewing_stand")); - map.put("TileEntityEnchantTable", new Identifier("enchanting_table")); - map.put("TileEntityEnderPortal", new Identifier("end_portal")); - map.put("TileEntityBeacon", new Identifier("beacon")); - map.put("TileEntitySkull", new Identifier("skull")); - map.put("TileEntityLightDetector", new Identifier("daylight_detector")); - map.put("TileEntityHopper", new Identifier("hopper")); - map.put("TileEntityComparator", new Identifier("comparator")); - map.put("TileEntityFlowerPot", new Identifier("flower_pot")); - map.put("TileEntityBanner", new Identifier("banner")); - map.put("TileEntityStructure", new Identifier("structure_block")); - map.put("TileEntityEndGateway", new Identifier("end_gateway")); - map.put("TileEntityCommand", new Identifier("command_block")); - map.put("TileEntityShulkerBox", new Identifier("shulker_box")); - map.put("TileEntityBed", new Identifier("bed")); + 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 Identifier getKey(String type) { - final Identifier key = OLD_ID_TO_KEY_MAP.get(type); + 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.NbtCompound cmp, String key, int sourceVer, int targetVer) { + 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.NbtCompound nbttagcompound, String key, int sourceVer, int 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.NbtCompound nbttagcompound, String key, int sourceVer, int targetVer) { + private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { if (nbttagcompound.contains(key, 9)) { - NbtList nbttaglist = nbttagcompound.getList(key, 10); + ListTag nbttaglist = nbttagcompound.getList(key, 10); for (int j = 0; j < nbttaglist.size(); ++j) { nbttaglist.add(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); @@ -619,19 +619,19 @@ public int getDataVersion() { } @Override - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { - NbtList nbttaglist = cmp.getList("Equipment", 10); - NbtList nbttaglist1; + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + ListTag nbttaglist = cmp.getList("Equipment", 10); + ListTag nbttaglist1; if (!nbttaglist.isEmpty() && !cmp.contains("HandItems", 10)) { - nbttaglist1 = new NbtList(); + nbttaglist1 = new ListTag(); nbttaglist1.add(nbttaglist.get(0)); - nbttaglist1.add(new net.minecraft.nbt.NbtCompound()); + nbttaglist1.add(new net.minecraft.nbt.CompoundTag()); cmp.put("HandItems", nbttaglist1); } if (nbttaglist.size() > 1 && !cmp.contains("ArmorItem", 10)) { - nbttaglist1 = new NbtList(); + nbttaglist1 = new ListTag(); nbttaglist1.add(nbttaglist.get(1)); nbttaglist1.add(nbttaglist.get(2)); nbttaglist1.add(nbttaglist.get(3)); @@ -642,21 +642,21 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) cmp.remove("Equipment"); if (cmp.contains("DropChances", 9)) { nbttaglist1 = cmp.getList("DropChances", 5); - NbtList nbttaglist2; + ListTag nbttaglist2; if (!cmp.contains("HandDropChances", 10)) { - nbttaglist2 = new NbtList(); - nbttaglist2.add(NbtFloat.of(nbttaglist1.getFloat(0))); - nbttaglist2.add(NbtFloat.of(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 NbtList(); - nbttaglist2.add(NbtFloat.of(nbttaglist1.getFloat(1))); - nbttaglist2.add(NbtFloat.of(nbttaglist1.getFloat(2))); - nbttaglist2.add(NbtFloat.of(nbttaglist1.getFloat(3))); - nbttaglist2.add(NbtFloat.of(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); } @@ -677,7 +677,7 @@ private static class DataInspectorBlockEntity implements DataInspector { @Nullable private static String convertEntityId(int i, String s) { - String key = new Identifier(s).toString(); + String key = new ResourceLocation(s).toString(); if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { return DataInspectorBlockEntity.b.get(key); } else { @@ -686,14 +686,14 @@ private static String convertEntityId(int i, String s) { } @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + 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.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); String s = cmp.getString("id"); String s1 = convertEntityId(sourceVer, s); boolean flag; @@ -818,11 +818,11 @@ private static class DataInspectorEntity implements DataInspector { } @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + 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.NbtCompound nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); String s = cmp.getString("id"); String s1; @@ -859,21 +859,21 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private abstract static class DataInspectorTagged implements DataInspector { - private final Identifier key; + private final ResourceLocation key; DataInspectorTagged(String type) { this.key = getKey(type); } - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - if (this.key.equals(new Identifier(cmp.getString("id")))) { + 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.NbtCompound inspectChecked(net.minecraft.nbt.NbtCompound nbttagcompound, int sourceVer, int targetVer); + abstract net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer); } private static class DataInspectorItemList extends DataInspectorTagged { @@ -885,7 +885,7 @@ private static class DataInspectorItemList extends DataInspectorTagged { this.keys = astring; } - net.minecraft.nbt.NbtCompound inspectChecked(net.minecraft.nbt.NbtCompound nbttagcompound, int sourceVer, int targetVer) { + net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String s : this.keys) { FabricDataFixer.convertItems(nbttagcompound, s, sourceVer, targetVer); } @@ -903,7 +903,7 @@ private static class DataInspectorItem extends DataInspectorTagged { this.keys = astring; } - net.minecraft.nbt.NbtCompound inspectChecked(net.minecraft.nbt.NbtCompound nbttagcompound, int sourceVer, int targetVer) { + net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String key : this.keys) { FabricDataFixer.convertItem(nbttagcompound, key, sourceVer, targetVer); } @@ -923,7 +923,7 @@ public int getDataVersion() { return 102; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if (cmp.contains("id", 99)) { short short0 = cmp.getShort("id"); @@ -1263,7 +1263,7 @@ public int getDataVersion() { return 147; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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"); } @@ -1281,20 +1281,20 @@ public int getDataVersion() { return 804; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + 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.NbtCompound nbttagcompound3 = nbttagcompound1.getCompound("display"); + net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display"); if (nbttagcompound3.contains("Lore", 9)) { - NbtList nbttaglist = nbttagcompound3.getList("Lore", 8); + ListTag nbttaglist = nbttagcompound3.getList("Lore", 8); if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0))) { return cmp; @@ -1329,9 +1329,9 @@ public int getDataVersion() { return 102; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("minecraft:potion".equals(cmp.getString("id"))) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); short short0 = cmp.getShort("Damage"); if (!nbttagcompound1.contains("Potion", 8)) { @@ -1495,10 +1495,10 @@ public int getDataVersion() { return 105; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); + 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)) { @@ -1602,7 +1602,7 @@ public int getDataVersion() { return 106; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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"); @@ -1628,13 +1628,13 @@ public int getDataVersion() { return 107; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound nbttagcompound1 = cmp.getCompound("SpawnData"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("SpawnData"); nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); cmp.put("SpawnData", nbttagcompound1); @@ -1642,13 +1642,13 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) } if (cmp.contains("SpawnPotentials", 9)) { - NbtList nbttaglist = cmp.getList("SpawnPotentials", 10); + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); for (int i = 0; i < nbttaglist.size(); ++i) { - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttaglist.getCompound(i); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); if (nbttagcompound2.contains("Type", 8)) { - net.minecraft.nbt.NbtCompound nbttagcompound3 = nbttagcompound2.getCompound("Properties"); + net.minecraft.nbt.CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Properties"); nbttagcompound3.putString("id", nbttagcompound2.getString("Type")); nbttagcompound2.put("Entity", nbttagcompound3); @@ -1672,9 +1672,9 @@ public int getDataVersion() { return 108; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if (cmp.contains("UUID", 8)) { - cmp.putUuid("UUID", UUID.fromString(cmp.getString("UUID"))); + cmp.putUUID("UUID", UUID.fromString(cmp.getString("UUID"))); } return cmp; @@ -1692,7 +1692,7 @@ public int getDataVersion() { return 109; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if (DataConverterHealth.a.contains(cmp.getString("id"))) { float f; @@ -1723,9 +1723,9 @@ public int getDataVersion() { return 110; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound nbttagcompound1 = new net.minecraft.nbt.NbtCompound(); + net.minecraft.nbt.CompoundTag nbttagcompound1 = new net.minecraft.nbt.CompoundTag(); nbttagcompound1.putString("id", "minecraft:saddle"); nbttagcompound1.putByte("Count", (byte) 1); @@ -1747,7 +1747,7 @@ public int getDataVersion() { return 111; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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); @@ -1756,20 +1756,20 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) Direction enumdirection; if (cmp.contains("Direction", 99)) { - enumdirection = Direction.fromHorizontal(cmp.getByte("Direction")); - cmp.putInt("TileX", cmp.getInt("TileX") + enumdirection.getOffsetX()); - cmp.putInt("TileY", cmp.getInt("TileY") + enumdirection.getOffsetY()); - cmp.putInt("TileZ", cmp.getInt("TileZ") + enumdirection.getOffsetZ()); + 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.fromHorizontal(cmp.getByte("Dir")); + enumdirection = Direction.from2DDataValue(cmp.getByte("Dir")); cmp.remove("Dir"); } - cmp.putByte("Facing", (byte) enumdirection.getHorizontal()); + cmp.putByte("Facing", (byte) enumdirection.get2DDataValue()); } return cmp; @@ -1785,8 +1785,8 @@ public int getDataVersion() { return 113; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { - NbtList nbttaglist; + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { + ListTag nbttaglist; if (cmp.contains("HandDropChances", 9)) { nbttaglist = cmp.getList("HandDropChances", 5); @@ -1815,9 +1815,9 @@ public int getDataVersion() { return 135; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { while (cmp.contains("Riding", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = this.b(cmp); + net.minecraft.nbt.CompoundTag nbttagcompound1 = this.b(cmp); this.convert(cmp, nbttagcompound1); cmp = nbttagcompound1; @@ -1826,15 +1826,15 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) return cmp; } - protected void convert(net.minecraft.nbt.NbtCompound nbttagcompound, net.minecraft.nbt.NbtCompound nbttagcompound1) { - NbtList nbttaglist = new NbtList(); + protected void convert(net.minecraft.nbt.CompoundTag nbttagcompound, net.minecraft.nbt.CompoundTag nbttagcompound1) { + ListTag nbttaglist = new ListTag(); nbttaglist.add(nbttagcompound); nbttagcompound1.put("Passengers", nbttaglist); } - protected net.minecraft.nbt.NbtCompound b(net.minecraft.nbt.NbtCompound nbttagcompound) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = nbttagcompound.getCompound("Riding"); + protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagcompound) { + net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Riding"); nbttagcompound.remove("Riding"); return nbttagcompound1; @@ -1850,12 +1850,12 @@ public int getDataVersion() { return 165; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("minecraft:written_book".equals(cmp.getString("id"))) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("pages", 9)) { - NbtList nbttaglist = nbttagcompound1.getList("pages", 8); + ListTag nbttaglist = nbttagcompound1.getList("pages", 8); for (int i = 0; i < nbttaglist.size(); ++i) { String s = nbttaglist.getString(i); @@ -1863,12 +1863,12 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) if (!"null".equals(s) && !Strings.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 LiteralText(s); + object = new TextComponent(s); } else { try { - object = JsonHelper.deserialize(DataConverterSignText.a, s, Text.class, true); + object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); if (object == null) { - object = new LiteralText(""); + object = new TextComponent(""); } } catch (JsonParseException jsonparseexception) { ; @@ -1876,7 +1876,7 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) if (object == null) { try { - object = Text.Serializer.fromJson(s); + object = Component.Serializer.fromJson(s); } catch (JsonParseException jsonparseexception1) { ; } @@ -1884,21 +1884,21 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) if (object == null) { try { - object = Text.Serializer.fromLenientJson(s); + object = Component.Serializer.fromJsonLenient(s); } catch (JsonParseException jsonparseexception2) { ; } } if (object == null) { - object = new LiteralText(s); + object = new TextComponent(s); } } } else { - object = new LiteralText(""); + object = new TextComponent(""); } - nbttaglist.set(i, NbtString.of(Text.Serializer.toJson((Text) object))); + nbttaglist.set(i, StringTag.valueOf(Component.Serializer.toJson((Component) object))); } nbttagcompound1.put("pages", nbttaglist); @@ -1911,7 +1911,7 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) private static class DataConverterCookedFish implements DataConverter { - private static final Identifier a = new Identifier("cooked_fished"); + private static final ResourceLocation a = new ResourceLocation("cooked_fished"); DataConverterCookedFish() { } @@ -1920,8 +1920,8 @@ public int getDataVersion() { return 502; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { - if (cmp.contains("id", 8) && DataConverterCookedFish.a.equals(new Identifier(cmp.getString("id")))) { + 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"); } @@ -1940,7 +1940,7 @@ public int getDataVersion() { return 502; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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; @@ -1980,7 +1980,7 @@ public int getDataVersion() { return 505; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { cmp.putString("useVbo", "true"); return cmp; } @@ -1995,7 +1995,7 @@ public int getDataVersion() { return 700; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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"); @@ -2017,7 +2017,7 @@ public int getDataVersion() { return 701; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { String s = cmp.getString("id"); if ("Skeleton".equals(s)) { @@ -2045,7 +2045,7 @@ public int getDataVersion() { return 702; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("Zombie".equals(cmp.getString("id"))) { int i = cmp.getInt("ZombieType"); @@ -2081,7 +2081,7 @@ public int getDataVersion() { return 703; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("EntityHorse".equals(cmp.getString("id"))) { int i = cmp.getInt("Type"); @@ -2126,7 +2126,7 @@ public int getDataVersion() { return 704; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { String s = DataConverterTileEntity.a.get(cmp.getString("id")); if (s != null) { @@ -2174,7 +2174,7 @@ public int getDataVersion() { return 704; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { String s = DataConverterEntity.a.get(cmp.getString("id")); if (s != null) { @@ -2272,11 +2272,11 @@ public int getDataVersion() { return 806; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (!nbttagcompound1.contains("Potion", 8)) { nbttagcompound1.putString("Potion", "minecraft:water"); @@ -2300,7 +2300,7 @@ public int getDataVersion() { return 808; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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); } @@ -2320,12 +2320,12 @@ public int getDataVersion() { return 813; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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.NbtCompound nbttagcompound1 = cmp.getCompound("tag"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); if (nbttagcompound2.getList("Items", 10).isEmpty()) { nbttagcompound2.remove("Items"); @@ -2359,7 +2359,7 @@ public int getDataVersion() { return 813; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { if ("minecraft:shulker".equals(cmp.getString("id"))) { cmp.remove("Color"); } @@ -2377,7 +2377,7 @@ public int getDataVersion() { return 816; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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)); } @@ -2395,7 +2395,7 @@ public int getDataVersion() { return 820; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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"); } @@ -2415,18 +2415,18 @@ public int getDataVersion() { return 1125; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { boolean flag = true; try { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("Level"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("Level"); int i = nbttagcompound1.getInt("xPos"); int j = nbttagcompound1.getInt("zPos"); - NbtList nbttaglist = nbttagcompound1.getList("TileEntities", 10); - NbtList 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.NbtCompound nbttagcompound2 = nbttaglist1.getCompound(k); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist1.getCompound(k); byte b0 = nbttagcompound2.getByte("Y"); byte[] abyte = nbttagcompound2.getByteArray("Blocks"); @@ -2435,7 +2435,7 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) int i1 = l & 15; int j1 = l >> 8 & 15; int k1 = l >> 4 & 15; - net.minecraft.nbt.NbtCompound nbttagcompound3 = new net.minecraft.nbt.NbtCompound(); + net.minecraft.nbt.CompoundTag nbttagcompound3 = new net.minecraft.nbt.CompoundTag(); nbttagcompound3.putString("id", "bed"); nbttagcompound3.putInt("x", i1 + (i << 4)); @@ -2462,7 +2462,7 @@ public int getDataVersion() { return 1125; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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()); } @@ -2473,18 +2473,18 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) private static class DataConverterSignText implements DataConverter { - public static final Gson a = new GsonBuilder().registerTypeAdapter(Text.class, new JsonDeserializer() { - MutableText a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + 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 LiteralText(jsonelement.getAsString()); + return new TextComponent(jsonelement.getAsString()); } else if (jsonelement.isJsonArray()) { JsonArray jsonarray = jsonelement.getAsJsonArray(); - MutableText iTextComponent = null; + MutableComponent iTextComponent = null; Iterator iterator = jsonarray.iterator(); while (iterator.hasNext()) { JsonElement jsonelement1 = iterator.next(); - MutableText iTextComponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); + MutableComponent iTextComponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); if (iTextComponent == null) { iTextComponent = iTextComponent1; @@ -2511,7 +2511,7 @@ public int getDataVersion() { return 101; } - public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) { + 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"); @@ -2522,18 +2522,18 @@ public net.minecraft.nbt.NbtCompound convert(net.minecraft.nbt.NbtCompound cmp) return cmp; } - private void convert(net.minecraft.nbt.NbtCompound nbttagcompound, String s) { + private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { String s1 = nbttagcompound.getString(s); Object object = null; if (!"null".equals(s1) && !Strings.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 LiteralText(s1); + object = new TextComponent(s1); } else { try { - object = JsonHelper.deserialize(DataConverterSignText.a, s1, Text.class, true); + object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); if (object == null) { - object = new LiteralText(""); + object = new TextComponent(""); } } catch (JsonParseException jsonparseexception) { ; @@ -2541,7 +2541,7 @@ private void convert(net.minecraft.nbt.NbtCompound nbttagcompound, String s) { if (object == null) { try { - object = Text.Serializer.fromJson(s1); + object = Component.Serializer.fromJson(s1); } catch (JsonParseException jsonparseexception1) { ; } @@ -2549,29 +2549,29 @@ private void convert(net.minecraft.nbt.NbtCompound nbttagcompound, String s) { if (object == null) { try { - object = Text.Serializer.fromLenientJson(s1); + object = Component.Serializer.fromJsonLenient(s1); } catch (JsonParseException jsonparseexception2) { ; } } if (object == null) { - object = new LiteralText(s1); + object = new TextComponent(s1); } } } else { - object = new LiteralText(""); + object = new TextComponent(""); } - nbttagcompound.putString(s, Text.Serializer.toJson((Text) object)); + nbttagcompound.putString(s, Component.Serializer.toJson((Component) object)); } } private static class DataInspectorPlayerVehicle implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("RootVehicle", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("RootVehicle"); + net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("RootVehicle"); if (nbttagcompound1.contains("Entity", 10)) { convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); @@ -2584,7 +2584,7 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private static class DataInspectorLevelPlayer implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + 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); } @@ -2595,16 +2595,16 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private static class DataInspectorStructure implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - NbtList nbttaglist; + public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + ListTag nbttaglist; int j; - net.minecraft.nbt.NbtCompound nbttagcompound1; + 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.NbtCompound) nbttaglist.get(j); + nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); if (nbttagcompound1.contains("nbt", 10)) { convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); } @@ -2615,7 +2615,7 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, nbttaglist = cmp.getList("blocks", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttagcompound1 = (net.minecraft.nbt.NbtCompound) nbttaglist.get(j); + nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); if (nbttagcompound1.contains("nbt", 10)) { convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); } @@ -2628,17 +2628,17 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private static class DataInspectorChunks implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("Level", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("Level"); - NbtList nbttaglist; + net.minecraft.nbt.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.NbtCompound) nbttaglist.get(j), sourceVer, targetVer)); + nbttaglist.set(j, convert(LegacyType.ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); } } @@ -2646,7 +2646,7 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, nbttaglist = nbttagcompound1.getList("TileEntities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (net.minecraft.nbt.NbtCompound) nbttaglist.get(j), sourceVer, targetVer)); + nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); } } } @@ -2657,9 +2657,9 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private static class DataInspectorEntityPassengers implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("Passengers", 9)) { - NbtList 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)); @@ -2672,7 +2672,7 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, private static class DataInspectorPlayer implements DataInspector { @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + 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)) { @@ -2688,18 +2688,18 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, } private static class DataInspectorVillagers implements DataInspector { - Identifier entityVillager = getKey("EntityVillager"); + ResourceLocation entityVillager = getKey("EntityVillager"); @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - if (entityVillager.equals(new Identifier(cmp.getString("id"))) && cmp.contains("Offers", 10)) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = cmp.getCompound("Offers"); + 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)) { - NbtList nbttaglist = nbttagcompound1.getList("Recipes", 10); + ListTag nbttaglist = nbttagcompound1.getList("Recipes", 10); for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.NbtCompound nbttagcompound2 = nbttaglist.getCompound(j); + net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist.getCompound(j); convertItem(nbttagcompound2, "buy", sourceVer, targetVer); convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); @@ -2714,13 +2714,13 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, } private static class DataInspectorMobSpawnerMinecart implements DataInspector { - Identifier entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); - Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); + ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); + ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { String s = cmp.getString("id"); - if (entityMinecartMobSpawner.equals(new Identifier(s))) { + if (entityMinecartMobSpawner.equals(new ResourceLocation(s))) { cmp.putString("id", tileEntityMobSpawner.toString()); convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); cmp.putString("id", s); @@ -2731,16 +2731,16 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, } private static class DataInspectorMobSpawnerMobs implements DataInspector { - Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); + ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - if (tileEntityMobSpawner.equals(new Identifier(cmp.getString("id")))) { + 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)) { - NbtList nbttaglist = cmp.getList("SpawnPotentials", 10); + ListTag nbttaglist = cmp.getList("SpawnPotentials", 10); for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.NbtCompound nbttagcompound1 = nbttaglist.getCompound(j); + net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); } @@ -2754,11 +2754,11 @@ public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, } private static class DataInspectorCommandBlock implements DataInspector { - Identifier tileEntityCommand = getKey("TileEntityCommand"); + ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); @Override - public net.minecraft.nbt.NbtCompound inspect(net.minecraft.nbt.NbtCompound cmp, int sourceVer, int targetVer) { - if (tileEntityCommand.equals(new Identifier(cmp.getString("id")))) { + 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"); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java index 79445141e..4293ba128 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java @@ -28,31 +28,30 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.entity.EntityTypes; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - import java.lang.ref.WeakReference; import javax.annotation.Nullable; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import static com.google.common.base.Preconditions.checkNotNull; class FabricEntity implements Entity { - private final WeakReference entityRef; + private final WeakReference entityRef; - FabricEntity(net.minecraft.entity.Entity entity) { + FabricEntity(net.minecraft.world.entity.Entity entity) { checkNotNull(entity); this.entityRef = new WeakReference<>(entity); } @Override public BaseEntity getState() { - net.minecraft.entity.Entity entity = entityRef.get(); + net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { - Identifier id = Registry.ENTITY_TYPE.getId(entity.getType()); - NbtCompound tag = new NbtCompound(); - entity.writeNbt(tag); + ResourceLocation id = Registry.ENTITY_TYPE.getKey(entity.getType()); + CompoundTag tag = new CompoundTag(); + entity.saveWithoutId(tag); return new BaseEntity(EntityTypes.get(id.toString()), NBTConverter.fromNative(tag)); } else { return null; @@ -61,13 +60,13 @@ public BaseEntity getState() { @Override public Location getLocation() { - net.minecraft.entity.Entity entity = entityRef.get(); + net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { Vector3 position = Vector3.at(entity.getX(), entity.getY(), entity.getZ()); - float yaw = entity.getYaw(); - float pitch = entity.getPitch(); + float yaw = entity.getYRot(); + float pitch = entity.getXRot(); - return new Location(FabricAdapter.adapt(entity.world), position, yaw, pitch); + return new Location(FabricAdapter.adapt(entity.level), position, yaw, pitch); } else { return new Location(NullWorld.getInstance()); } @@ -81,9 +80,9 @@ public boolean setLocation(Location location) { @Override public Extent getExtent() { - net.minecraft.entity.Entity entity = entityRef.get(); + net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { - return FabricAdapter.adapt(entity.world); + return FabricAdapter.adapt(entity.level); } else { return NullWorld.getInstance(); } @@ -91,9 +90,9 @@ public Extent getExtent() { @Override public boolean remove() { - net.minecraft.entity.Entity entity = entityRef.get(); + net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { - entity.remove(net.minecraft.entity.Entity.RemovalReason.KILLED); + entity.remove(net.minecraft.world.entity.Entity.RemovalReason.KILLED); } return true; } @@ -102,7 +101,7 @@ public boolean remove() { @Nullable @Override public T getFacet(Class cls) { - net.minecraft.entity.Entity entity = entityRef.get(); + net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { if (EntityProperties.class.isAssignableFrom(cls)) { return (T) new FabricEntityProperties(entity); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java index 19c91e383..cacfb2092 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java @@ -20,28 +20,28 @@ package com.sk89q.worldedit.fabric; import com.sk89q.worldedit.entity.metadata.EntityProperties; -import net.minecraft.entity.Entity; -import net.minecraft.entity.ExperienceOrbEntity; -import net.minecraft.entity.FallingBlockEntity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.Npc; -import net.minecraft.entity.TntEntity; -import net.minecraft.entity.boss.dragon.EnderDragonEntity; -import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.entity.decoration.ItemFrameEntity; -import net.minecraft.entity.decoration.painting.PaintingEntity; -import net.minecraft.entity.mob.AmbientEntity; -import net.minecraft.entity.mob.MobEntity; -import net.minecraft.entity.mob.WaterCreatureEntity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.passive.GolemEntity; -import net.minecraft.entity.passive.TameableEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.entity.vehicle.AbstractMinecartEntity; -import net.minecraft.entity.vehicle.BoatEntity; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.village.Merchant; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.ambient.AmbientCreature; +import net.minecraft.world.entity.animal.AbstractGolem; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.animal.WaterAnimal; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.npc.Npc; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.trading.Merchant; import static com.google.common.base.Preconditions.checkNotNull; @@ -56,12 +56,12 @@ public FabricEntityProperties(Entity entity) { @Override public boolean isPlayerDerived() { - return entity instanceof PlayerEntity; + return entity instanceof Player; } @Override public boolean isProjectile() { - return entity instanceof ProjectileEntity; + return entity instanceof Projectile; } @Override @@ -76,47 +76,47 @@ public boolean isFallingBlock() { @Override public boolean isPainting() { - return entity instanceof PaintingEntity; + return entity instanceof Painting; } @Override public boolean isItemFrame() { - return entity instanceof ItemFrameEntity; + return entity instanceof ItemFrame; } @Override public boolean isBoat() { - return entity instanceof BoatEntity; + return entity instanceof Boat; } @Override public boolean isMinecart() { - return entity instanceof AbstractMinecartEntity; + return entity instanceof AbstractMinecart; } @Override public boolean isTNT() { - return entity instanceof TntEntity; + return entity instanceof PrimedTnt; } @Override public boolean isExperienceOrb() { - return entity instanceof ExperienceOrbEntity; + return entity instanceof ExperienceOrb; } @Override public boolean isLiving() { - return entity instanceof MobEntity; + return entity instanceof Mob; } @Override public boolean isAnimal() { - return entity instanceof AnimalEntity; + return entity instanceof Animal; } @Override public boolean isAmbient() { - return entity instanceof AmbientEntity; + return entity instanceof AmbientCreature; } @Override @@ -126,12 +126,12 @@ public boolean isNPC() { @Override public boolean isGolem() { - return entity instanceof GolemEntity; + return entity instanceof AbstractGolem; } @Override public boolean isTamed() { - return entity instanceof TameableEntity && ((TameableEntity) entity).isTamed(); + return entity instanceof TamableAnimal && ((TamableAnimal) entity).isTame(); } @Override @@ -141,16 +141,16 @@ public boolean isTagged() { @Override public boolean isArmorStand() { - return entity instanceof ArmorStandEntity; + return entity instanceof ArmorStand; } @Override public boolean isPasteable() { - return !(entity instanceof ServerPlayerEntity || entity instanceof EnderDragonEntity); + return !(entity instanceof ServerPlayer || entity instanceof EnderDragon); } @Override public boolean isWaterCreature() { - return entity instanceof WaterCreatureEntity; + return entity instanceof WaterAnimal; } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java index c48419f03..43d0bc72c 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java @@ -21,20 +21,19 @@ import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; -import net.minecraft.tag.ItemTags; -import net.minecraft.tag.Tag; -import net.minecraft.util.Identifier; - import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.Tag; public class FabricItemCategoryRegistry implements ItemCategoryRegistry { @Override public Set getCategorisedByName(String category) { - return Optional.ofNullable(ItemTags.getTagGroup().getTag(new Identifier(category))) - .map(Tag::values) + return Optional.ofNullable(ItemTags.getAllTags().getTag(new ResourceLocation(category))) + .map(Tag::getValues) .orElse(Collections.emptyList()) .stream() .map(FabricAdapter::adapt) diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java index 8218b932f..bd3d74c40 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java @@ -30,14 +30,14 @@ public class FabricItemRegistry extends BundledItemRegistry { @Override public Component getRichName(ItemType itemType) { return TranslatableComponent.of( - FabricAdapter.adapt(itemType).getTranslationKey() + FabricAdapter.adapt(itemType).getDescriptionId() ); } @Override public Component getRichName(BaseItemStack itemStack) { return TranslatableComponent.of( - FabricAdapter.adapt(itemStack).getTranslationKey() + FabricAdapter.adapt(itemStack).getDescriptionId() ); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java index ccf4532bd..8d7cf9edd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java @@ -20,12 +20,12 @@ package com.sk89q.worldedit.fabric; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.world.GameMode; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.GameType; public interface FabricPermissionsProvider { - boolean hasPermission(ServerPlayerEntity player, String permission); + boolean hasPermission(ServerPlayer player, String permission); void registerPermission(String permission); @@ -38,11 +38,11 @@ public VanillaPermissionsProvider(FabricPlatform platform) { } @Override - public boolean hasPermission(ServerPlayerEntity player, String permission) { + public boolean hasPermission(ServerPlayer player, String permission) { FabricConfiguration configuration = platform.getConfiguration(); return configuration.cheatMode - || player.server.getPlayerManager().isOperator(player.getGameProfile()) - || (configuration.creativeEnable && player.interactionManager.getGameMode() == GameMode.CREATIVE); + || player.server.getPlayerList().isOp(player.getGameProfile()) + || (configuration.creativeEnable && player.gameMode.getGameModeForPlayer() == GameType.CREATIVE); } @Override @@ -57,7 +57,7 @@ public LuckoFabricPermissionsProvider(FabricPlatform platform) { } @Override - public boolean hasPermission(ServerPlayerEntity player, String permission) { + public boolean hasPermission(ServerPlayer player, String permission) { return Permissions.getPermissionValue(player, permission) .orElseGet(() -> super.hasPermission(player, permission)); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index 9c901c97b..5cfb220a6 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -21,7 +21,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Sets; -import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.AbstractPlatform; import com.sk89q.worldedit.extension.platform.Actor; @@ -32,24 +31,21 @@ import com.sk89q.worldedit.fabric.internal.ExtendedChunk; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.lifecycle.Lifecycled; -import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.minecraft.SharedConstants; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerManager; -import net.minecraft.server.dedicated.MinecraftDedicatedServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.chunk.WorldChunk; -import net.minecraft.world.level.ServerWorldProperties; -import org.enginehub.piston.Command; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.storage.ServerLevelData; import org.enginehub.piston.CommandManager; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -59,9 +55,6 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; -import javax.annotation.Nullable; - -import static java.util.stream.Collectors.toList; class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { @@ -75,7 +68,7 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { this.dataFixer = new FabricDataFixer(getDataVersion()); this.watchdog = FabricWorldEdit.LIFECYCLED_SERVER.map( - server -> server instanceof MinecraftDedicatedServer + server -> server instanceof DedicatedServer ? Optional.of((Watchdog) server) : Optional.empty() ); @@ -92,7 +85,7 @@ public Registries getRegistries() { @Override public int getDataVersion() { - return SharedConstants.getGameVersion().getWorldVersion(); + return SharedConstants.getCurrentVersion().getDataVersion().getVersion(); } @Override @@ -102,7 +95,7 @@ public DataFixer getDataFixer() { @Override public boolean isValidMobType(String type) { - return Registry.ENTITY_TYPE.containsId(new Identifier(type)); + return Registry.ENTITY_TYPE.containsKey(new ResourceLocation(type)); } @Override @@ -124,9 +117,9 @@ public Watchdog getWatchdog() { @Override public List getWorlds() { - Iterable worlds = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getWorlds(); + Iterable worlds = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getAllLevels(); List ret = new ArrayList<>(); - for (ServerWorld world : worlds) { + for (ServerLevel world : worlds) { ret.add(new FabricWorld(world)); } return ret; @@ -138,8 +131,8 @@ public Player matchPlayer(Player player) { if (player instanceof FabricPlayer) { return player; } else { - ServerPlayerEntity entity = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow() - .getPlayerManager().getPlayer(player.getName()); + ServerPlayer entity = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow() + .getPlayerList().getPlayerByName(player.getName()); return entity != null ? new FabricPlayer(entity) : null; } } @@ -150,8 +143,8 @@ public World matchWorld(World world) { if (world instanceof FabricWorld) { return world; } else { - for (ServerWorld ws : FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getWorlds()) { - if (((ServerWorldProperties) ws.getLevelProperties()).getLevelName().equals(world.getName())) { + for (ServerLevel ws : FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getAllLevels()) { + if (((ServerLevelData) ws.getLevelData()).getLevelName().equals(world.getName())) { return new FabricWorld(ws); } } @@ -215,7 +208,7 @@ public Map getCapabilities() { @Override public Set getSupportedSideEffects() { - return ExtendedChunk.class.isAssignableFrom(WorldChunk.class) + return ExtendedChunk.class.isAssignableFrom(LevelChunk.class) ? SUPPORTED_SIDE_EFFECTS : SUPPORTED_SIDE_EFFECTS_NO_MIXIN; } @@ -223,8 +216,8 @@ public Set getSupportedSideEffects() { @Override public Collection getConnectedUsers() { List users = new ArrayList<>(); - PlayerManager scm = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getPlayerManager(); - for (ServerPlayerEntity entity : scm.getPlayerList()) { + PlayerList scm = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getPlayerList(); + for (ServerPlayer entity : scm.getPlayers()) { if (entity != null) { users.add(new FabricPlayer(entity)); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 98ac05eb1..09db25a25 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.fabric.internal.ExtendedPlayerEntity; import com.sk89q.worldedit.fabric.internal.NBTConverter; +import com.sk89q.worldedit.fabric.mixin.AccessorClientboundBlockEntityDataPacket; import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.math.BlockVector3; @@ -44,50 +45,48 @@ import com.sk89q.worldedit.world.block.BlockTypes; import io.netty.buffer.Unpooled; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.item.ItemStack; -import net.minecraft.network.MessageType; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; -import net.minecraft.text.MutableText; -import net.minecraft.util.Formatting; -import net.minecraft.util.Hand; -import net.minecraft.util.Util; -import net.minecraft.util.math.BlockPos; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.UUID; -import javax.annotation.Nullable; public class FabricPlayer extends AbstractPlayerActor { - // see ClientPlayNetHandler: search for "invalid update packet", lots of hardcoded consts - private static final int STRUCTURE_BLOCK_PACKET_ID = 7; - private final ServerPlayerEntity player; + private final ServerPlayer player; - protected FabricPlayer(ServerPlayerEntity player) { + protected FabricPlayer(ServerPlayer player) { this.player = player; ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); } @Override public UUID getUniqueId() { - return player.getUuid(); + return player.getUUID(); } @Override public BaseItemStack getItemInHand(HandSide handSide) { - ItemStack is = this.player.getStackInHand(handSide == HandSide.MAIN_HAND ? Hand.MAIN_HAND : Hand.OFF_HAND); + ItemStack is = this.player.getItemInHand(handSide == HandSide.MAIN_HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); return FabricAdapter.adapt(is); } @Override public String getName() { - return this.player.getName().asString(); + return this.player.getName().getContents(); } @Override @@ -99,16 +98,16 @@ public BaseEntity getState() { public Location getLocation() { Vector3 position = Vector3.at(this.player.getX(), this.player.getY(), this.player.getZ()); return new Location( - FabricWorldEdit.inst.getWorld(this.player.world), + FabricWorldEdit.inst.getWorld(this.player.level), position, - this.player.getYaw(), - this.player.getPitch()); + this.player.getYRot(), + this.player.getXRot()); } @Override public boolean setLocation(Location location) { - ServerWorld level = (ServerWorld) FabricAdapter.adapt((World) location.getExtent()); - this.player.teleport( + ServerLevel level = (ServerLevel) FabricAdapter.adapt((World) location.getExtent()); + this.player.teleportTo( level, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch() @@ -116,17 +115,17 @@ public boolean setLocation(Location location) { // This check doesn't really ever get to be false in Fabric // Since Fabric API doesn't allow cancelling the teleport. // However, other mods could theoretically mix this in, so allow the detection. - return this.player.getServerWorld() == level; + return this.player.getLevel() == level; } @Override public World getWorld() { - return FabricWorldEdit.inst.getWorld(this.player.world); + return FabricWorldEdit.inst.getWorld(this.player.level); } @Override public void giveItem(BaseItemStack itemStack) { - this.player.getInventory().insertStack(FabricAdapter.adapt(itemStack)); + this.player.getInventory().add(FabricAdapter.adapt(itemStack)); } @Override @@ -139,7 +138,7 @@ public void dispatchCUIEvent(CUIEvent event) { ServerPlayNetworking.send( this.player, WECUIPacketHandler.CUI_IDENTIFIER, - new PacketByteBuf(Unpooled.copiedBuffer(send, StandardCharsets.UTF_8)) + new FriendlyByteBuf(Unpooled.copiedBuffer(send, StandardCharsets.UTF_8)) ); } @@ -152,44 +151,44 @@ public Locale getLocale() { @Deprecated public void printRaw(String msg) { for (String part : msg.split("\n")) { - this.player.sendMessage(new LiteralText(part), MessageType.SYSTEM, Util.NIL_UUID); + this.player.sendMessage(new TextComponent(part), ChatType.SYSTEM, Util.NIL_UUID); } } @Override @Deprecated public void printDebug(String msg) { - sendColorized(msg, Formatting.GRAY); + sendColorized(msg, ChatFormatting.GRAY); } @Override @Deprecated public void print(String msg) { - sendColorized(msg, Formatting.LIGHT_PURPLE); + sendColorized(msg, ChatFormatting.LIGHT_PURPLE); } @Override @Deprecated public void printError(String msg) { - sendColorized(msg, Formatting.RED); + sendColorized(msg, ChatFormatting.RED); } @Override public void print(Component component) { - this.player.sendMessage(net.minecraft.text.Text.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale()))), false); + this.player.displayClientMessage(net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale()))), false); } - private void sendColorized(String msg, Formatting formatting) { + private void sendColorized(String msg, ChatFormatting formatting) { for (String part : msg.split("\n")) { - MutableText component = new LiteralText(part) - .styled(style -> style.withColor(formatting)); - this.player.sendMessage(component, false); + MutableComponent component = new TextComponent(part) + .withStyle(style -> style.withColor(formatting)); + this.player.displayClientMessage(component, false); } } @Override public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { - this.player.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); + this.player.connection.teleport(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); return true; } @@ -216,14 +215,14 @@ public T getFacet(Class cls) { @Override public boolean isAllowedToFly() { - return player.getAbilities().allowFlying; + return player.getAbilities().mayfly; } @Override public void setFlying(boolean flying) { if (player.getAbilities().flying != flying) { player.getAbilities().flying = flying; - player.sendAbilitiesUpdate(); + player.onUpdateAbilities(); } } @@ -235,20 +234,20 @@ public > void sendFakeBlock(BlockVector3 pos, B bl } BlockPos loc = FabricAdapter.toBlockPos(pos); if (block == null) { - final BlockUpdateS2CPacket packetOut = new BlockUpdateS2CPacket(((FabricWorld) world).getWorld(), loc); - player.networkHandler.sendPacket(packetOut); + final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket(((FabricWorld) world).getWorld(), loc); + player.connection.send(packetOut); } else { - final BlockUpdateS2CPacket packetOut = new BlockUpdateS2CPacket( + final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( loc, FabricAdapter.adapt(block.toImmutableState()) ); - player.networkHandler.sendPacket(packetOut); + player.connection.send(packetOut); if (block instanceof BaseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { final CompoundTag nbtData = ((BaseBlock) block).getNbtData(); if (nbtData != null) { - player.networkHandler.sendPacket(new BlockEntityUpdateS2CPacket( + player.connection.send(AccessorClientboundBlockEntityDataPacket.construct( new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - STRUCTURE_BLOCK_PACKET_ID, + BlockEntityType.STRUCTURE_BLOCK, NBTConverter.toNative(nbtData)) ); } @@ -267,8 +266,8 @@ static class SessionKeyImpl implements SessionKey { private final UUID uuid; private final String name; - SessionKeyImpl(ServerPlayerEntity player) { - this.uuid = player.getUuid(); + SessionKeyImpl(ServerPlayer player) { + this.uuid = player.getUUID(); this.name = player.getName().getString(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index 176e5efa2..851dacd2d 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -38,8 +38,8 @@ import com.sk89q.worldedit.fabric.internal.ExtendedMinecraftServer; import com.sk89q.worldedit.fabric.internal.FabricWorldNativeAccess; import com.sk89q.worldedit.fabric.internal.NBTConverter; -import com.sk89q.worldedit.fabric.mixin.AccessorLevelProperties; -import com.sk89q.worldedit.fabric.mixin.AccessorServerChunkManager; +import com.sk89q.worldedit.fabric.mixin.AccessorPrimaryLevelData; +import com.sk89q.worldedit.fabric.mixin.AccessorServerChunkCache; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; @@ -60,45 +60,44 @@ import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.weather.WeatherType; import com.sk89q.worldedit.world.weather.WeatherTypes; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsageContext; -import net.minecraft.nbt.NbtElement; +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.data.worldgen.features.EndFeatures; +import net.minecraft.data.worldgen.features.TreeFeatures; import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.RegistryReadOps; +import net.minecraft.resources.RegistryWriteOps; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerChunkManager; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Clearable; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; -import net.minecraft.util.dynamic.RegistryOps; -import net.minecraft.util.dynamic.RegistryReadingOps; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.World; -import net.minecraft.world.WorldProperties; -import net.minecraft.world.biome.source.BiomeAccessType; -import net.minecraft.world.biome.source.BiomeArray; -import net.minecraft.world.biome.source.HorizontalVoronoiBiomeAccessType; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.ChunkManager; -import net.minecraft.world.chunk.ChunkStatus; -import net.minecraft.world.chunk.WorldChunk; -import net.minecraft.world.dimension.DimensionOptions; -import net.minecraft.world.gen.GeneratorOptions; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.ConfiguredFeatures; -import net.minecraft.world.level.ServerWorldProperties; -import net.minecraft.world.level.storage.LevelStorage; - +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Clearable; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkSource; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.storage.LevelData; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.ServerLevelData; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; import java.lang.ref.WeakReference; import java.nio.file.Files; import java.nio.file.Path; @@ -127,14 +126,14 @@ public class FabricWorld extends AbstractWorld { private static final Random random = new Random(); - private static Identifier getDimensionRegistryKey(World world) { + private static ResourceLocation getDimensionRegistryKey(Level world) { return Objects.requireNonNull(world.getServer(), "server cannot be null") - .getRegistryManager() - .get(Registry.DIMENSION_TYPE_KEY) - .getId(world.getDimension()); + .registryAccess() + .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY) + .getKey(world.dimensionType()); } - private final WeakReference worldRef; + private final WeakReference worldRef; private final FabricWorldNativeAccess worldNativeAccess; /** @@ -142,7 +141,7 @@ private static Identifier getDimensionRegistryKey(World world) { * * @param world the world */ - FabricWorld(World world) { + FabricWorld(Level world) { checkNotNull(world); this.worldRef = new WeakReference<>(world); this.worldNativeAccess = new FabricWorldNativeAccess(worldRef); @@ -154,8 +153,8 @@ private static Identifier getDimensionRegistryKey(World world) { * @return the world * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) */ - public World getWorld() { - World world = worldRef.get(); + public Level getWorld() { + Level world = worldRef.get(); if (world != null) { return world; } else { @@ -165,8 +164,8 @@ public World getWorld() { @Override public String getName() { - WorldProperties levelProperties = getWorld().getLevelProperties(); - return ((ServerWorldProperties) levelProperties).getLevelName(); + LevelData levelProperties = getWorld().getLevelData(); + return ((ServerLevelData) levelProperties).getLevelName(); } @Override @@ -176,7 +175,7 @@ public String getId() { @Override public Path getStoragePath() { - final World world = getWorld(); + final Level world = getWorld(); MinecraftServer server = world.getServer(); checkState(server instanceof ExtendedMinecraftServer, "Need a server world"); return ((ExtendedMinecraftServer) server).getStoragePath(world); @@ -197,7 +196,7 @@ public Set applySideEffects(BlockVector3 position, BlockState previo @Override public int getBlockLightLevel(BlockVector3 position) { checkNotNull(position); - return getWorld().getLightLevel(FabricAdapter.toBlockPos(position)); + return getWorld().getMaxLocalRawBrightness(FabricAdapter.toBlockPos(position)); } @Override @@ -206,28 +205,21 @@ public boolean clearContainerBlockContents(BlockVector3 position) { BlockEntity tile = getWorld().getBlockEntity(FabricAdapter.toBlockPos(position)); if ((tile instanceof Clearable)) { - ((Clearable) tile).clear(); + ((Clearable) tile).clearContent(); return true; } return false; } - @Override - public boolean fullySupports3DBiomes() { - BiomeAccessType biomeAccessType = getWorld().getDimension().getBiomeAccessType(); - return !(biomeAccessType instanceof HorizontalVoronoiBiomeAccessType); - } - @Override public BiomeType getBiome(BlockVector3 position) { checkNotNull(position); - Chunk chunk = getWorld().getChunk(position.getX() >> 4, position.getZ() >> 4); + ChunkAccess chunk = getWorld().getChunk(position.getX() >> 4, position.getZ() >> 4); return getBiomeInChunk(position, chunk); } - private BiomeType getBiomeInChunk(BlockVector3 position, Chunk chunk) { - BiomeArray biomeArray = checkNotNull(chunk.getBiomeArray()); - return FabricAdapter.adapt(biomeArray.getBiomeForNoiseGen(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2)); + private BiomeType getBiomeInChunk(BlockVector3 position, ChunkAccess chunk) { + return FabricAdapter.adapt(chunk.getNoiseBiome(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2)); } @Override @@ -235,42 +227,45 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { checkNotNull(position); checkNotNull(biome); - Chunk chunk = getWorld().getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4); - MutableBiomeArray biomeArray = MutableBiomeArray.inject(checkNotNull(chunk.getBiomeArray())); - biomeArray.setBiome(position.getX(), position.getY(), position.getZ(), FabricAdapter.adapt(biome)); - chunk.setShouldSave(true); + ChunkAccess chunk = getWorld().getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4); + PalettedContainer biomeArray = chunk.getSection(chunk.getSectionIndex(position.getY())).getBiomes(); + biomeArray.getAndSetUnchecked( + position.getX() & 3, position.getY() & 3, position.getZ() & 3, + FabricAdapter.adapt(biome) + ); + chunk.setUnsaved(true); return true; } - private static final LoadingCache fakePlayers + private static final LoadingCache fakePlayers = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(WorldEditFakePlayer::new)); @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtData(), 1)); - ServerWorld world = (ServerWorld) getWorld(); + ServerLevel world = (ServerLevel) getWorld(); final WorldEditFakePlayer fakePlayer; try { fakePlayer = fakePlayers.get(world); } catch (ExecutionException ignored) { return false; } - fakePlayer.setStackInHand(Hand.MAIN_HAND, stack); - fakePlayer.updatePositionAndAngles(position.getBlockX(), position.getBlockY(), position.getBlockZ(), + 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 = FabricAdapter.toBlockPos(position); final BlockHitResult rayTraceResult = new BlockHitResult(FabricAdapter.toVec3(position), FabricAdapter.adapt(face), blockPos, false); - ItemUsageContext itemUseContext = new ItemUsageContext(fakePlayer, Hand.MAIN_HAND, rayTraceResult); - ActionResult used = stack.useOnBlock(itemUseContext); - if (used != ActionResult.SUCCESS) { + UseOnContext itemUseContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); + InteractionResult used = stack.useOn(itemUseContext); + if (used != InteractionResult.SUCCESS) { // try activating the block - used = getWorld().getBlockState(blockPos).onUse(world, fakePlayer, Hand.MAIN_HAND, rayTraceResult); + used = getWorld().getBlockState(blockPos).use(world, fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); } - if (used != ActionResult.SUCCESS) { - used = stack.use(world, fakePlayer, Hand.MAIN_HAND).getResult(); + if (used != InteractionResult.SUCCESS) { + used = stack.use(world, fakePlayer, InteractionHand.MAIN_HAND).getResult(); } - return used == ActionResult.SUCCESS; + return used == InteractionResult.SUCCESS; } @Override @@ -283,26 +278,26 @@ public void dropItem(Vector3 position, BaseItemStack item) { } ItemEntity entity = new ItemEntity(getWorld(), position.getX(), position.getY(), position.getZ(), FabricAdapter.adapt(item)); - entity.setPickupDelay(10); - getWorld().spawnEntity(entity); + entity.setPickUpDelay(10); + getWorld().addFreshEntity(entity); } @Override public void simulateBlockMine(BlockVector3 position) { BlockPos pos = FabricAdapter.toBlockPos(position); - getWorld().breakBlock(pos, true); + getWorld().destroyBlock(pos, true); } @Override public boolean canPlaceAt(BlockVector3 position, BlockState blockState) { - return FabricAdapter.adapt(blockState).canPlaceAt(getWorld(), FabricAdapter.toBlockPos(position)); + return FabricAdapter.adapt(blockState).canSurvive(getWorld(), FabricAdapter.toBlockPos(position)); } @Override public boolean regenerate(Region region, Extent extent, RegenOptions options) { // Don't even try to regen if it's going to fail. - ChunkManager provider = getWorld().getChunkManager(); - if (!(provider instanceof ServerChunkManager)) { + ChunkSource provider = getWorld().getChunkSource(); + if (!(provider instanceof ServerChunkCache)) { return false; } @@ -317,30 +312,30 @@ public boolean regenerate(Region region, Extent extent, RegenOptions options) { private void doRegen(Region region, Extent extent, RegenOptions options) throws Exception { Path tempDir = Files.createTempDirectory("WorldEditWorldGen"); - LevelStorage levelStorage = LevelStorage.create(tempDir); - try (LevelStorage.Session session = levelStorage.createSession("WorldEditTempGen")) { - ServerWorld originalWorld = (ServerWorld) getWorld(); - AccessorLevelProperties levelProperties = (AccessorLevelProperties) - originalWorld.getLevelProperties(); - GeneratorOptions originalOpts = levelProperties.getGeneratorOptions(); + LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); + try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("WorldEditTempGen")) { + ServerLevel originalWorld = (ServerLevel) getWorld(); + AccessorPrimaryLevelData levelProperties = (AccessorPrimaryLevelData) + originalWorld.getLevelData(); + WorldGenSettings originalOpts = levelProperties.worldGenSettings(); long seed = options.getSeed().orElse(originalWorld.getSeed()); - GeneratorOptions newOpts = options.getSeed().isPresent() + WorldGenSettings newOpts = options.getSeed().isPresent() ? replaceSeed(originalWorld, seed, originalOpts) : originalOpts; - levelProperties.setGeneratorOptions(newOpts); - RegistryKey worldRegKey = originalWorld.getRegistryKey(); - DimensionOptions dimGenOpts = newOpts.getDimensions().get(worldRegKey.getValue()); + levelProperties.setWorldGenSettings(newOpts); + ResourceKey worldRegKey = originalWorld.dimension(); + LevelStem dimGenOpts = newOpts.dimensions().get(worldRegKey.location()); checkNotNull(dimGenOpts, "No DimensionOptions for %s", worldRegKey); - try (ServerWorld serverWorld = new ServerWorld( - originalWorld.getServer(), Util.getMainWorkerExecutor(), session, - ((ServerWorldProperties) originalWorld.getLevelProperties()), + try (ServerLevel serverWorld = new ServerLevel( + originalWorld.getServer(), Util.backgroundExecutor(), session, + ((ServerLevelData) originalWorld.getLevelData()), worldRegKey, - originalWorld.getDimension(), + originalWorld.dimensionType(), new WorldEditGenListener(), - dimGenOpts.getChunkGenerator(), - originalWorld.isDebugWorld(), + dimGenOpts.generator(), + originalWorld.isDebug(), seed, // No spawners are needed for this world. ImmutableList.of(), @@ -350,32 +345,32 @@ private void doRegen(Region region, Extent extent, RegenOptions options) throws regenForWorld(region, extent, serverWorld, options); // drive the server executor until all tasks are popped off - while (originalWorld.getServer().runTask()) { + while (originalWorld.getServer().pollTask()) { Thread.yield(); } } finally { - levelProperties.setGeneratorOptions(originalOpts); + levelProperties.setWorldGenSettings(originalOpts); } } finally { SafeFiles.tryHardToDeleteDir(tempDir); } } - private GeneratorOptions replaceSeed(ServerWorld originalWorld, long seed, GeneratorOptions originalOpts) { - RegistryReadingOps nbtRegReadOps = RegistryReadingOps.of( + private WorldGenSettings replaceSeed(ServerLevel originalWorld, long seed, WorldGenSettings originalOpts) { + RegistryWriteOps nbtRegReadOps = RegistryWriteOps.create( NbtOps.INSTANCE, - originalWorld.getServer().getRegistryManager() + originalWorld.getServer().registryAccess() ); - RegistryOps nbtRegOps = RegistryOps.method_36574( + RegistryReadOps nbtRegOps = RegistryReadOps.create( NbtOps.INSTANCE, ((ExtendedMinecraftServer) originalWorld.getServer()) - .getServerResourceManager().getResourceManager(), - originalWorld.getServer().getRegistryManager() + .getResources().getResourceManager(), + originalWorld.getServer().registryAccess() ); - return GeneratorOptions.CODEC + return WorldGenSettings.CODEC .encodeStart(nbtRegReadOps, originalOpts) .flatMap(tag -> - GeneratorOptions.CODEC.parse( + WorldGenSettings.CODEC.parse( recursivelySetSeed(new Dynamic<>(nbtRegOps, tag), seed, new HashSet<>()) ) ) @@ -389,7 +384,7 @@ private GeneratorOptions replaceSeed(ServerWorld originalWorld, long seed, Gener } @SuppressWarnings("unchecked") - private Dynamic recursivelySetSeed(Dynamic dynamic, long seed, Set> seen) { + private Dynamic recursivelySetSeed(Dynamic dynamic, long seed, Set> seen) { if (!seen.add(dynamic)) { return dynamic; } @@ -397,20 +392,20 @@ private Dynamic recursivelySetSeed(Dynamic dynamic, long if (pair.getFirst().asString("").equals("seed")) { return pair.mapSecond(v -> v.createLong(seed)); } - if (pair.getSecond().getValue() instanceof net.minecraft.nbt.NbtCompound) { - return pair.mapSecond(v -> recursivelySetSeed((Dynamic) v, seed, seen)); + if (pair.getSecond().getValue() instanceof net.minecraft.nbt.CompoundTag) { + return pair.mapSecond(v -> recursivelySetSeed((Dynamic) v, seed, seen)); } return pair; }); } - private void regenForWorld(Region region, Extent extent, ServerWorld serverWorld, + private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws WorldEditException { - List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); + List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); // drive executor until loading finishes - ((AccessorServerChunkManager) serverWorld.getChunkManager()).getMainThreadExecutor() - .runTasks(() -> { + ((AccessorServerChunkCache) serverWorld.getChunkSource()).getMainThreadProcessor() + .managedBlock(() -> { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> ftr.isDone() && Futures.getUnchecked(ftr) == null @@ -420,23 +415,21 @@ private void regenForWorld(Region region, Extent extent, ServerWorld serverWorld return chunkLoadings.stream().allMatch(CompletableFuture::isDone); }); - Map chunks = new HashMap<>(); - for (CompletableFuture future : chunkLoadings) { + Map chunks = new HashMap<>(); + for (CompletableFuture future : chunkLoadings) { @Nullable - Chunk chunk = future.getNow(null); + 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 = FabricAdapter.toBlockPos(vec); - Chunk chunk = chunks.get(new ChunkPos(pos)); + ChunkAccess chunk = chunks.get(new ChunkPos(pos)); BlockStateHolder state = FabricAdapter.adapt(chunk.getBlockState(pos)); BlockEntity blockEntity = chunk.getBlockEntity(pos); if (blockEntity != null) { - net.minecraft.nbt.NbtCompound tag = new net.minecraft.nbt.NbtCompound(); - blockEntity.writeNbt(tag); - state = state.toBaseBlock(NBTConverter.fromNative(tag)); + state = state.toBaseBlock(NBTConverter.fromNative(blockEntity.saveWithId())); } extent.setBlock(vec, state.toBaseBlock()); @@ -447,9 +440,9 @@ private void regenForWorld(Region region, Extent extent, ServerWorld serverWorld } } - private List> submitChunkLoadTasks(Region region, ServerWorld world) { - AccessorServerChunkManager chunkManager = (AccessorServerChunkManager) world.getChunkManager(); - List> chunkLoadings = new ArrayList<>(); + private List> submitChunkLoadTasks(Region region, ServerLevel world) { + AccessorServerChunkCache chunkManager = (AccessorServerChunkCache) world.getChunkSource(); + List> chunkLoadings = new ArrayList<>(); // Pre-gen all the chunks for (BlockVector2 chunk : region.getChunks()) { chunkLoadings.add( @@ -462,40 +455,39 @@ private List> submitChunkLoadTasks(Region region, Serve @Nullable private static ConfiguredFeature createTreeFeatureGenerator(TreeType type) { - switch (type) { + return switch (type) { // Based off of the SaplingGenerator class, as well as uses of DefaultBiomeFeatures fields - case TREE: return ConfiguredFeatures.OAK; - case BIG_TREE: return ConfiguredFeatures.FANCY_OAK; - case REDWOOD: return ConfiguredFeatures.SPRUCE; - case TALL_REDWOOD: return ConfiguredFeatures.MEGA_SPRUCE; - case MEGA_REDWOOD: return ConfiguredFeatures.MEGA_PINE; - case BIRCH: return ConfiguredFeatures.BIRCH; - case JUNGLE: return ConfiguredFeatures.MEGA_JUNGLE_TREE; - case SMALL_JUNGLE: return ConfiguredFeatures.JUNGLE_TREE; - case SHORT_JUNGLE: return ConfiguredFeatures.JUNGLE_TREE_NO_VINE; - case JUNGLE_BUSH: return ConfiguredFeatures.JUNGLE_BUSH; - case SWAMP: return ConfiguredFeatures.SWAMP_OAK; - case ACACIA: return ConfiguredFeatures.ACACIA; - case DARK_OAK: return ConfiguredFeatures.DARK_OAK; - case TALL_BIRCH: return ConfiguredFeatures.SUPER_BIRCH_BEES_0002; - case RED_MUSHROOM: return ConfiguredFeatures.HUGE_RED_MUSHROOM; - case BROWN_MUSHROOM: return ConfiguredFeatures.HUGE_BROWN_MUSHROOM; - case WARPED_FUNGUS: return ConfiguredFeatures.WARPED_FUNGI; - case CRIMSON_FUNGUS: return ConfiguredFeatures.CRIMSON_FUNGI; - case CHORUS_PLANT: return ConfiguredFeatures.CHORUS_PLANT; - case RANDOM: return createTreeFeatureGenerator(TreeType.values()[ThreadLocalRandom.current().nextInt(TreeType.values().length)]); - default: - return null; - } + case TREE -> TreeFeatures.OAK; + case BIG_TREE -> TreeFeatures.FANCY_OAK; + case REDWOOD -> TreeFeatures.SPRUCE; + case TALL_REDWOOD -> TreeFeatures.MEGA_SPRUCE; + case MEGA_REDWOOD -> TreeFeatures.MEGA_PINE; + case BIRCH -> TreeFeatures.BIRCH; + case JUNGLE -> TreeFeatures.MEGA_JUNGLE_TREE; + case SMALL_JUNGLE -> TreeFeatures.JUNGLE_TREE; + case SHORT_JUNGLE -> TreeFeatures.JUNGLE_TREE_NO_VINE; + case JUNGLE_BUSH -> TreeFeatures.JUNGLE_BUSH; + case SWAMP -> TreeFeatures.SWAMP_OAK; + case ACACIA -> TreeFeatures.ACACIA; + case DARK_OAK -> TreeFeatures.DARK_OAK; + case TALL_BIRCH -> TreeFeatures.SUPER_BIRCH_BEES_0002; + case RED_MUSHROOM -> TreeFeatures.HUGE_RED_MUSHROOM; + case BROWN_MUSHROOM -> TreeFeatures.HUGE_BROWN_MUSHROOM; + case WARPED_FUNGUS -> TreeFeatures.WARPED_FUNGUS; + case CRIMSON_FUNGUS -> TreeFeatures.CRIMSON_FUNGUS; + case CHORUS_PLANT -> EndFeatures.CHORUS_PLANT; + case RANDOM -> createTreeFeatureGenerator(TreeType.values()[ThreadLocalRandom.current().nextInt(TreeType.values().length)]); + default -> null; + }; } @Override public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 position) { ConfiguredFeature generator = createTreeFeatureGenerator(type); - ServerWorld world = (ServerWorld) getWorld(); - ServerChunkManager chunkManager = world.getChunkManager(); - return generator != null && generator.generate( - world, chunkManager.getChunkGenerator(), random, + ServerLevel world = (ServerLevel) getWorld(); + ServerChunkCache chunkManager = world.getChunkSource(); + return generator != null && generator.place( + world, chunkManager.getGenerator(), random, FabricAdapter.toBlockPos(position) ); } @@ -512,9 +504,9 @@ public void fixAfterFastMode(Iterable chunks) { @Override public void fixLighting(Iterable chunks) { - World world = getWorld(); + Level world = getWorld(); for (BlockVector2 chunk : chunks) { - world.getChunkManager().getLightingProvider().setColumnEnabled( + world.getChunkSource().getLightEngine().enableLightSources( new ChunkPos(chunk.getBlockX(), chunk.getBlockZ()), true ); } @@ -529,7 +521,7 @@ public boolean playEffect(Vector3 position, int type, int data) { @Override public WeatherType getWeather() { - WorldProperties info = getWorld().getLevelProperties(); + LevelData info = getWorld().getLevelData(); if (info.isThundering()) { return WeatherTypes.THUNDER_STORM; } @@ -541,7 +533,7 @@ public WeatherType getWeather() { @Override public long getRemainingWeatherDuration() { - ServerWorldProperties info = (ServerWorldProperties) getWorld().getLevelProperties(); + ServerLevelData info = (ServerLevelData) getWorld().getLevelData(); if (info.isThundering()) { return info.getThunderTime(); } @@ -558,7 +550,7 @@ public void setWeather(WeatherType weatherType) { @Override public void setWeather(WeatherType weatherType, long duration) { - ServerWorldProperties info = (ServerWorldProperties) getWorld().getLevelProperties(); + ServerLevelData info = (ServerLevelData) getWorld().getLevelData(); if (weatherType == WeatherTypes.THUNDER_STORM) { info.setClearWeatherTime(0); info.setThundering(true); @@ -576,27 +568,27 @@ public void setWeather(WeatherType weatherType, long duration) { @Override public int getMinY() { - return getWorld().getBottomY(); + return getWorld().getMinBuildHeight(); } @Override public int getMaxY() { - return getWorld().getTopY() - 1; + return getWorld().getMaxBuildHeight() - 1; } @Override public BlockVector3 getSpawnPosition() { - WorldProperties worldProps = getWorld().getLevelProperties(); + LevelData worldProps = getWorld().getLevelData(); return BlockVector3.at( - worldProps.getSpawnX(), - worldProps.getSpawnY(), - worldProps.getSpawnZ() + worldProps.getXSpawn(), + worldProps.getYSpawn(), + worldProps.getZSpawn() ); } @Override public BlockState getBlock(BlockVector3 position) { - net.minecraft.block.BlockState mcState = getWorld() + net.minecraft.world.level.block.state.BlockState mcState = getWorld() .getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4) .getBlockState(FabricAdapter.toBlockPos(position)); @@ -607,12 +599,10 @@ public BlockState getBlock(BlockVector3 position) { public BaseBlock getFullBlock(BlockVector3 position) { BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); // Avoid creation by using the CHECK mode -- if it's needed, it'll be re-created anyways - BlockEntity tile = ((WorldChunk) getWorld().getChunk(pos)).getBlockEntity(pos, WorldChunk.CreationType.CHECK); + BlockEntity tile = ((LevelChunk) getWorld().getChunk(pos)).getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); if (tile != null) { - net.minecraft.nbt.NbtCompound tag = new net.minecraft.nbt.NbtCompound(); - tile.writeNbt(tag); - return getBlock(position).toBaseBlock(NBTConverter.fromNative(tag)); + return getBlock(position).toBaseBlock(NBTConverter.fromNative(tile.saveWithId())); } else { return getBlock(position).toBaseBlock(); } @@ -625,10 +615,9 @@ public int hashCode() { @Override public boolean equals(Object o) { - if ((o instanceof FabricWorld)) { - FabricWorld other = ((FabricWorld) o); - World otherWorld = other.worldRef.get(); - World thisWorld = worldRef.get(); + if ((o instanceof FabricWorld other)) { + Level otherWorld = other.worldRef.get(); + Level thisWorld = worldRef.get(); return otherWorld != null && otherWorld.equals(thisWorld); } else if (o instanceof com.sk89q.worldedit.world.World) { return ((com.sk89q.worldedit.world.World) o).getName().equals(getName()); @@ -639,15 +628,15 @@ public boolean equals(Object o) { @Override public List getEntities(Region region) { - final World world = getWorld(); - Box box = new Box( + final Level world = getWorld(); + AABB box = new AABB( FabricAdapter.toBlockPos(region.getMinimumPoint()), FabricAdapter.toBlockPos(region.getMaximumPoint().add(BlockVector3.ONE)) ); - List nmsEntities = world.getOtherEntities( - null, + List nmsEntities = world.getEntities( + (net.minecraft.world.entity.Entity) null, box, - e -> region.contains(FabricAdapter.adapt(e.getBlockPos())) + e -> region.contains(FabricAdapter.adapt(e.blockPosition())) ); return nmsEntities.stream() .map(FabricEntity::new) @@ -656,11 +645,11 @@ public List getEntities(Region region) { @Override public List getEntities() { - final World world = getWorld(); - if (!(world instanceof ServerWorld)) { + final Level world = getWorld(); + if (!(world instanceof ServerLevel)) { return Collections.emptyList(); } - return Streams.stream(((ServerWorld) world).iterateEntities()) + return Streams.stream(((ServerLevel) world).getAllEntities()) .map(FabricEntity::new) .collect(ImmutableList.toImmutableList()); } @@ -668,25 +657,25 @@ public List getEntities() { @Nullable @Override public Entity createEntity(Location location, BaseEntity entity) { - World world = getWorld(); - final Optional> entityType = EntityType.get(entity.getType().getId()); - if (!entityType.isPresent()) { + Level world = getWorld(); + final Optional> entityType = EntityType.byString(entity.getType().getId()); + if (entityType.isEmpty()) { return null; } - net.minecraft.entity.Entity createdEntity = entityType.get().create(world); + net.minecraft.world.entity.Entity createdEntity = entityType.get().create(world); if (createdEntity != null) { CompoundTag nativeTag = entity.getNbtData(); if (nativeTag != null) { - net.minecraft.nbt.NbtCompound tag = NBTConverter.toNative(entity.getNbtData()); + net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(entity.getNbtData()); for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } - createdEntity.readNbt(tag); + createdEntity.load(tag); } - createdEntity.updatePositionAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - world.spawnEntity(createdEntity); + world.addFreshEntity(createdEntity); return new FabricEntity(createdEntity); } else { return null; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java index 6d2ff9c96..7950821ff 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java @@ -52,23 +52,23 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.tag.BlockTags; -import net.minecraft.tag.ItemTags; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.TypedActionResult; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.World; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; import org.apache.logging.log4j.Logger; import org.enginehub.piston.Command; @@ -153,7 +153,7 @@ public void onInitialize() { LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded"); } - private void registerCommands(CommandDispatcher dispatcher, boolean dedicated) { + private void registerCommands(CommandDispatcher dispatcher, boolean dedicated) { WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent()); PlatformManager manager = WorldEdit.getInstance().getPlatformManager(); Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS); @@ -187,37 +187,37 @@ private FabricPermissionsProvider getInitialPermissionsProvider() { private void setupRegistries(MinecraftServer server) { // Blocks - for (Identifier name : Registry.BLOCK.getIds()) { + for (ResourceLocation name : Registry.BLOCK.keySet()) { if (BlockType.REGISTRY.get(name.toString()) == null) { BlockType.REGISTRY.register(name.toString(), new BlockType(name.toString(), - input -> FabricAdapter.adapt(FabricAdapter.adapt(input.getBlockType()).getDefaultState()))); + input -> FabricAdapter.adapt(FabricAdapter.adapt(input.getBlockType()).defaultBlockState()))); } } // Items - for (Identifier name : Registry.ITEM.getIds()) { + for (ResourceLocation name : Registry.ITEM.keySet()) { if (ItemType.REGISTRY.get(name.toString()) == null) { ItemType.REGISTRY.register(name.toString(), new ItemType(name.toString())); } } // Entities - for (Identifier name : Registry.ENTITY_TYPE.getIds()) { + for (ResourceLocation name : Registry.ENTITY_TYPE.keySet()) { if (EntityType.REGISTRY.get(name.toString()) == null) { EntityType.REGISTRY.register(name.toString(), new EntityType(name.toString())); } } // Biomes - for (Identifier name : server.getRegistryManager().get(Registry.BIOME_KEY).getIds()) { + for (ResourceLocation name : server.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).keySet()) { if (BiomeType.REGISTRY.get(name.toString()) == null) { BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString())); } } // Tags - for (Identifier name : BlockTags.getTagGroup().getTagIds()) { + for (ResourceLocation name : BlockTags.getAllTags().getAvailableTags()) { if (BlockCategory.REGISTRY.get(name.toString()) == null) { BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString())); } } - for (Identifier name : ItemTags.getTagGroup().getTagIds()) { + for (ResourceLocation name : ItemTags.getAllTags().getAvailableTags()) { if (ItemCategory.REGISTRY.get(name.toString()) == null) { ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString())); } @@ -252,13 +252,13 @@ private boolean shouldSkip() { return !platform.isHookingEvents(); // We have to be told to catch these events } - private ActionResult onLeftClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockPos blockPos, Direction direction) { - if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) { - return ActionResult.PASS; + private InteractionResult onLeftClickBlock(Player playerEntity, Level world, InteractionHand hand, BlockPos blockPos, Direction direction) { + if (shouldSkip() || hand == InteractionHand.OFF_HAND || world.isClientSide) { + return InteractionResult.PASS; } WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity); + FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); FabricWorld localWorld = getWorld(world); Location pos = new Location(localWorld, blockPos.getX(), @@ -268,61 +268,61 @@ private ActionResult onLeftClickBlock(PlayerEntity playerEntity, World world, Ha com.sk89q.worldedit.util.Direction weDirection = FabricAdapter.adaptEnumFacing(direction); if (we.handleBlockLeftClick(player, pos, weDirection)) { - return ActionResult.SUCCESS; + return InteractionResult.SUCCESS; } if (we.handleArmSwing(player)) { - return ActionResult.SUCCESS; + return InteractionResult.SUCCESS; } - return ActionResult.PASS; + return InteractionResult.PASS; } - private ActionResult onRightClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) { - if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) { - return ActionResult.PASS; + private InteractionResult onRightClickBlock(Player playerEntity, Level world, InteractionHand hand, BlockHitResult blockHitResult) { + if (shouldSkip() || hand == InteractionHand.OFF_HAND || world.isClientSide) { + return InteractionResult.PASS; } WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity); + FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); FabricWorld localWorld = getWorld(world); Location pos = new Location(localWorld, blockHitResult.getBlockPos().getX(), blockHitResult.getBlockPos().getY(), blockHitResult.getBlockPos().getZ() ); - com.sk89q.worldedit.util.Direction direction = FabricAdapter.adaptEnumFacing(blockHitResult.getSide()); + com.sk89q.worldedit.util.Direction direction = FabricAdapter.adaptEnumFacing(blockHitResult.getDirection()); if (we.handleBlockRightClick(player, pos, direction)) { - return ActionResult.SUCCESS; + return InteractionResult.SUCCESS; } if (we.handleRightClick(player)) { - return ActionResult.SUCCESS; + return InteractionResult.SUCCESS; } - return ActionResult.PASS; + return InteractionResult.PASS; } - private TypedActionResult onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) { - ItemStack stackInHand = playerEntity.getStackInHand(hand); - if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) { - return TypedActionResult.pass(stackInHand); + private InteractionResultHolder onRightClickAir(Player playerEntity, Level world, InteractionHand hand) { + ItemStack stackInHand = playerEntity.getItemInHand(hand); + if (shouldSkip() || hand == InteractionHand.OFF_HAND || world.isClientSide) { + return InteractionResultHolder.pass(stackInHand); } WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity); + FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); if (we.handleRightClick(player)) { - return TypedActionResult.success(stackInHand); + return InteractionResultHolder.success(stackInHand); } - return TypedActionResult.pass(stackInHand); + return InteractionResultHolder.pass(stackInHand); } // TODO Pass empty left click to server - private void onPlayerDisconnect(ServerPlayNetworkHandler handler, MinecraftServer server) { + private void onPlayerDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server) { WorldEdit.getInstance().getEventBus() .post(new SessionIdleEvent(new FabricPlayer.SessionKeyImpl(handler.player))); } @@ -342,7 +342,7 @@ FabricConfiguration getConfig() { * @param player the player * @return the session */ - public LocalSession getSession(ServerPlayerEntity player) { + public LocalSession getSession(ServerPlayer player) { checkNotNull(player); return WorldEdit.getInstance().getSessionManager().get(adaptPlayer(player)); } @@ -353,7 +353,7 @@ public LocalSession getSession(ServerPlayerEntity player) { * @param world the world * @return the WorldEdit world */ - public FabricWorld getWorld(World world) { + public FabricWorld getWorld(Level world) { checkNotNull(world); return new FabricWorld(world); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/MutableBiomeArray.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/MutableBiomeArray.java deleted file mode 100644 index 19721aef5..000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/MutableBiomeArray.java +++ /dev/null @@ -1,42 +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.fabric; - -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.BiomeArray; - -/** - * Interface over a {@link BiomeArray} as a mutable object. - */ -public interface MutableBiomeArray { - - /** - * Hook into the given biome array, to allow edits on it. - * @param biomeArray the biome array to edit - * @return the mutable interface to the biome array - */ - static MutableBiomeArray inject(BiomeArray biomeArray) { - // It's Mixin'd - return (MutableBiomeArray) biomeArray; - } - - void setBiome(int x, int y, int z, Biome biome); - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java index 4aba1e1ab..e9408e2bf 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java @@ -21,8 +21,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - +import net.minecraft.server.level.ServerPlayer; import java.util.HashSet; import java.util.Set; import java.util.UUID; @@ -57,9 +56,9 @@ public void onEndTick(MinecraftServer server) { if (server == null) { return; } - for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { + for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player != null) { - onlineIds.add(player.getUuid()); + onlineIds.add(player.getUUID()); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java index 3af452cc3..ef19f5247 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java @@ -20,18 +20,17 @@ package com.sk89q.worldedit.fabric; import com.mojang.authlib.GameProfile; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.stat.Stat; -import net.minecraft.text.Text; - import java.util.UUID; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.Stat; +import net.minecraft.world.damagesource.DamageSource; -public class WorldEditFakePlayer extends ServerPlayerEntity { +public class WorldEditFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); - public WorldEditFakePlayer(ServerWorld world) { + public WorldEditFakePlayer(ServerLevel world) { super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); } @@ -40,16 +39,16 @@ public void tick() { } @Override - public void increaseStat(Stat stat, int incrementer) { + public void awardStat(Stat stat, int incrementer) { } @Override - public void incrementStat(Stat stat) { + public void awardStat(Stat stat) { } @Override - public void sendMessage(Text message, boolean actionBar) { - super.sendMessage(message, actionBar); + public void displayClientMessage(Component message, boolean actionBar) { + super.displayClientMessage(message, actionBar); } @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java index 3392a4c67..b069d1a95 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java @@ -21,14 +21,13 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.server.WorldGenerationProgressListener; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.chunk.ChunkStatus; - +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkStatus; import javax.annotation.Nullable; // For now, this does nothing, but might be useful later for regen progress communication. -class WorldEditGenListener implements WorldGenerationProgressListener { +class WorldEditGenListener implements ChunkProgressListener { @Environment(EnvType.CLIENT) @Override @@ -36,11 +35,11 @@ public void start() { } @Override - public void start(ChunkPos spawnPos) { + public void updateSpawnPos(ChunkPos spawnPos) { } @Override - public void setChunkStatus(ChunkPos pos, @Nullable ChunkStatus status) { + public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { } @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java index 3092f24c0..b89e4157d 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java @@ -20,15 +20,14 @@ package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.util.SideEffect; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.Chunk; - import javax.annotation.Nullable; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; public interface ExtendedChunk { /** - * {@link Chunk#setBlockState(BlockPos, BlockState, boolean)} with the extra + * {@link ChunkAccess#setBlockState(BlockPos, BlockState, boolean)} with the extra * {@link SideEffect#UPDATE} flag. * * @param pos the position to set diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java index d3a0765c1..ebb801c54 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java @@ -19,15 +19,14 @@ package com.sk89q.worldedit.fabric.internal; -import net.minecraft.resource.ServerResourceManager; -import net.minecraft.world.World; - import java.nio.file.Path; +import net.minecraft.server.ServerResources; +import net.minecraft.world.level.Level; public interface ExtendedMinecraftServer { - Path getStoragePath(World world); + Path getStoragePath(Level world); - ServerResourceManager getServerResourceManager(); + ServerResources getResources(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java index 9b758d7ee..224e4e5d4 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java @@ -28,52 +28,51 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.block.BlockType; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.util.StringIdentifiable; - import java.util.Comparator; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.DirectionProperty; /** * Raw, un-cached transformations. */ public class FabricTransmogrifier { - public static Property transmogToWorldEditProperty(net.minecraft.state.property.Property property) { - if (property instanceof net.minecraft.state.property.BooleanProperty) { - return new BooleanProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.property.BooleanProperty) property).getValues())); + public static Property transmogToWorldEditProperty(net.minecraft.world.level.block.state.properties.Property property) { + if (property instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.world.level.block.state.properties.BooleanProperty) property).getPossibleValues())); } - if (property instanceof net.minecraft.state.property.IntProperty) { - return new IntegerProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.property.IntProperty) property).getValues())); + if (property instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.world.level.block.state.properties.IntegerProperty) property).getPossibleValues())); } if (property instanceof DirectionProperty) { - return new DirectionalProperty(property.getName(), ((DirectionProperty) property).getValues().stream() + return new DirectionalProperty(property.getName(), ((DirectionProperty) property).getPossibleValues().stream() .map(FabricAdapter::adaptEnumFacing) .collect(Collectors.toList())); } - if (property instanceof net.minecraft.state.property.EnumProperty) { + if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { // Note: do not make x.asString a method reference. // It will cause runtime bootstrap exceptions. - return new EnumProperty(property.getName(), ((net.minecraft.state.property.EnumProperty) property).getValues().stream() - .map(x -> x.asString()) + return new EnumProperty(property.getName(), ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getPossibleValues().stream() + .map(x -> x.getSerializedName()) .collect(Collectors.toList())); } return new PropertyAdapter<>(property); } - private static Map, Object> transmogToWorldEditProperties(BlockType block, Map, Comparable> mcProps) { + private static Map, Object> transmogToWorldEditProperties(BlockType block, Map, Comparable> mcProps) { Map, Object> props = new TreeMap<>(Comparator.comparing(Property::getName)); - for (Map.Entry, Comparable> prop : mcProps.entrySet()) { + for (Map.Entry, Comparable> prop : mcProps.entrySet()) { Object value = prop.getValue(); if (prop.getKey() instanceof DirectionProperty) { - value = FabricAdapter.adaptEnumFacing((net.minecraft.util.math.Direction) value); - } else if (prop.getKey() instanceof net.minecraft.state.property.EnumProperty) { - value = ((StringIdentifiable) value).asString(); + value = FabricAdapter.adaptEnumFacing((net.minecraft.core.Direction) value); + } else if (prop.getKey() instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + value = ((StringRepresentable) value).getSerializedName(); } props.put(block.getProperty(prop.getKey().getName()), value); } @@ -81,37 +80,37 @@ private static Map, Object> transmogToWorldEditProperties(BlockType } @SuppressWarnings({ "unchecked", "rawtypes" }) - private static net.minecraft.block.BlockState transmogToMinecraftProperties(StateManager stateContainer, - net.minecraft.block.BlockState newState, Map, Object> states) { + private static net.minecraft.world.level.block.state.BlockState transmogToMinecraftProperties(StateDefinition stateContainer, + net.minecraft.world.level.block.state.BlockState newState, Map, Object> states) { for (Map.Entry, Object> state : states.entrySet()) { - net.minecraft.state.property.Property property = stateContainer.getProperty(state.getKey().getName()); + 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 = FabricAdapter.adapt(dir); - } else if (property instanceof net.minecraft.state.property.EnumProperty) { + } else if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { String enumName = (String) value; - value = ((net.minecraft.state.property.EnumProperty) property).parse((String) value).orElseGet(() -> { + value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getValue((String) value).orElseGet(() -> { throw new IllegalStateException("Enum property " + property.getName() + " does not contain " + enumName); }); } - newState = newState.with(property, value); + newState = newState.setValue(property, value); } return newState; } - public static net.minecraft.block.BlockState transmogToMinecraft(com.sk89q.worldedit.world.block.BlockState blockState) { + public static net.minecraft.world.level.block.state.BlockState transmogToMinecraft(com.sk89q.worldedit.world.block.BlockState blockState) { Block mcBlock = FabricAdapter.adapt(blockState.getBlockType()); - net.minecraft.block.BlockState newState = mcBlock.getDefaultState(); + net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); Map, Object> states = blockState.getStates(); - return transmogToMinecraftProperties(mcBlock.getStateManager(), newState, states); + return transmogToMinecraftProperties(mcBlock.getStateDefinition(), newState, states); } - public static com.sk89q.worldedit.world.block.BlockState transmogToWorldEdit(net.minecraft.block.BlockState blockState) { + public static com.sk89q.worldedit.world.block.BlockState transmogToWorldEdit(net.minecraft.world.level.block.state.BlockState blockState) { BlockType blockType = FabricAdapter.adapt(blockState.getBlock()); - return blockType.getState(transmogToWorldEditProperties(blockType, blockState.getEntries())); + return blockType.getState(transmogToWorldEditProperties(blockType, blockState.getValues())); } private FabricTransmogrifier() { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java index 063cfa18b..ea20ce60d 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java @@ -25,32 +25,31 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.storage.ChunkStore; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.world.ChunkHolder; -import net.minecraft.server.world.ServerChunkManager; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.WorldChunk; - import java.lang.ref.WeakReference; import java.util.Objects; import javax.annotation.Nullable; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +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.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; -public class FabricWorldNativeAccess implements WorldNativeAccess { +public class FabricWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; private static final int NOTIFY = 2; - private final WeakReference world; + private final WeakReference world; private SideEffectSet sideEffectSet; - public FabricWorldNativeAccess(WeakReference world) { + public FabricWorldNativeAccess(WeakReference world) { this.world = world; } - private World getWorld() { + private Level getWorld() { return Objects.requireNonNull(world.get(), "The reference to the world was lost"); } @@ -60,7 +59,7 @@ public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { } @Override - public WorldChunk getChunk(int x, int z) { + public LevelChunk getChunk(int x, int z) { return getWorld().getChunk(x, z); } @@ -68,18 +67,18 @@ public WorldChunk getChunk(int x, int z) { public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { int stateId = BlockStateIdAccess.getBlockStateId(state); return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.getStateFromRawId(stateId) + ? Block.stateById(stateId) : FabricAdapter.adapt(state); } @Override - public BlockState getBlockState(WorldChunk chunk, BlockPos position) { + public BlockState getBlockState(LevelChunk chunk, BlockPos position) { return chunk.getBlockState(position); } @Nullable @Override - public BlockState setBlockState(WorldChunk chunk, BlockPos position, BlockState state) { + public BlockState setBlockState(LevelChunk chunk, BlockPos position, BlockState state) { if (chunk instanceof ExtendedChunk) { return ((ExtendedChunk) chunk).setBlockState( position, state, false, sideEffectSet.shouldApply(SideEffect.UPDATE) @@ -90,7 +89,7 @@ public BlockState setBlockState(WorldChunk chunk, BlockPos position, BlockState @Override public BlockState getValidBlockForPosition(BlockState block, BlockPos position) { - return Block.postProcessState(block, getWorld(), position); + return Block.updateFromNeighbourShapes(block, getWorld(), position); } @Override @@ -100,58 +99,58 @@ public BlockPos getPosition(int x, int y, int z) { @Override public void updateLightingForBlock(BlockPos position) { - getWorld().getChunkManager().getLightingProvider().checkBlock(position); + getWorld().getChunkSource().getLightEngine().checkBlock(position); } @Override public boolean updateTileEntity(BlockPos position, com.sk89q.jnbt.CompoundTag tag) { - NbtCompound nativeTag = NBTConverter.toNative(tag); - BlockEntity tileEntity = getWorld().getWorldChunk(position).getBlockEntity(position); + CompoundTag nativeTag = NBTConverter.toNative(tag); + BlockEntity tileEntity = getWorld().getChunkAt(position).getBlockEntity(position); if (tileEntity == null) { return false; } - tileEntity.readNbt(nativeTag); - tileEntity.markDirty(); + tileEntity.load(nativeTag); + tileEntity.setChanged(); return true; } @Override - public void notifyBlockUpdate(WorldChunk chunk, BlockPos position, BlockState oldState, BlockState newState) { - if (chunk.getSectionArray()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().updateListeners(position, oldState, newState, UPDATE | NOTIFY); + public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, BlockState oldState, BlockState newState) { + if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { + getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); } } @Override - public boolean isChunkTicking(WorldChunk chunk) { - return chunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING); + public boolean isChunkTicking(LevelChunk chunk) { + return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); } @Override - public void markBlockChanged(WorldChunk chunk, BlockPos position) { - if (chunk.getSectionArray()[getWorld().getSectionIndex(position.getY())] != null) { - ((ServerChunkManager) getWorld().getChunkManager()).markForUpdate(position); + public void markBlockChanged(LevelChunk chunk, BlockPos position) { + if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { + ((ServerChunkCache) getWorld().getChunkSource()).blockChanged(position); } } @Override public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { - getWorld().updateNeighbors(pos, oldState.getBlock()); - if (newState.hasComparatorOutput()) { - getWorld().updateComparators(pos, newState.getBlock()); + getWorld().blockUpdated(pos, oldState.getBlock()); + if (newState.hasAnalogOutputSignal()) { + getWorld().updateNeighbourForOutputSignal(pos, newState.getBlock()); } } @Override public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState, int recursionLimit) { - World world = getWorld(); - oldState.prepare(world, pos, NOTIFY, recursionLimit); - newState.updateNeighbors(world, pos, NOTIFY, recursionLimit); - newState.prepare(world, pos, NOTIFY, recursionLimit); + Level world = getWorld(); + oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); + newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit); + newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); } @Override public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { - getWorld().onBlockChanged(pos, oldState, newState); + getWorld().onBlockStateChange(pos, oldState, newState); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java index 8366952f3..d3aebc8ad 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java @@ -47,7 +47,7 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - if (mixinClassName.equals("com.sk89q.worldedit.fabric.mixin.MixinWorldChunkSetBlockHook")) { + if (mixinClassName.equals("com.sk89q.worldedit.fabric.mixin.MixinLevelChunkSetBlockHook")) { List conflictingContainers = Stream.of("carpet", "quickcarpet") .map(FabricLoader.getInstance()::getModContainer) .filter(Optional::isPresent) 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 ef7ab4f88..e8652e597 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 @@ -50,7 +50,7 @@ public final class NBTConverter { private NBTConverter() { } - public static net.minecraft.nbt.NbtElement toNative(Tag tag) { + public static net.minecraft.nbt.Tag toNative(Tag tag) { if (tag instanceof IntArrayTag) { return toNative((IntArrayTag) tag); @@ -91,13 +91,13 @@ public static net.minecraft.nbt.NbtElement toNative(Tag tag) { } } - public static net.minecraft.nbt.NbtIntArray toNative(IntArrayTag tag) { + public static net.minecraft.nbt.IntArrayTag toNative(IntArrayTag tag) { int[] value = tag.getValue(); - return new net.minecraft.nbt.NbtIntArray(Arrays.copyOf(value, value.length)); + return new net.minecraft.nbt.IntArrayTag(Arrays.copyOf(value, value.length)); } - public static net.minecraft.nbt.NbtList toNative(ListTag tag) { - net.minecraft.nbt.NbtList list = new net.minecraft.nbt.NbtList(); + public static net.minecraft.nbt.ListTag toNative(ListTag tag) { + net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag(); for (Tag child : tag.getValue()) { if (child instanceof EndTag) { continue; @@ -107,100 +107,100 @@ public static net.minecraft.nbt.NbtList toNative(ListTag tag) { return list; } - public static net.minecraft.nbt.NbtLong toNative(LongTag tag) { - return net.minecraft.nbt.NbtLong.of(tag.getValue()); + public static net.minecraft.nbt.LongTag toNative(LongTag tag) { + return net.minecraft.nbt.LongTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtLongArray toNative(LongArrayTag tag) { - return new net.minecraft.nbt.NbtLongArray(tag.getValue().clone()); + public static net.minecraft.nbt.LongArrayTag toNative(LongArrayTag tag) { + return new net.minecraft.nbt.LongArrayTag(tag.getValue().clone()); } - public static net.minecraft.nbt.NbtString toNative(StringTag tag) { - return net.minecraft.nbt.NbtString.of(tag.getValue()); + public static net.minecraft.nbt.StringTag toNative(StringTag tag) { + return net.minecraft.nbt.StringTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtInt toNative(IntTag tag) { - return net.minecraft.nbt.NbtInt.of(tag.getValue()); + public static net.minecraft.nbt.IntTag toNative(IntTag tag) { + return net.minecraft.nbt.IntTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtByte toNative(ByteTag tag) { - return net.minecraft.nbt.NbtByte.of(tag.getValue()); + public static net.minecraft.nbt.ByteTag toNative(ByteTag tag) { + return net.minecraft.nbt.ByteTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtByteArray toNative(ByteArrayTag tag) { - return new net.minecraft.nbt.NbtByteArray(tag.getValue().clone()); + public static net.minecraft.nbt.ByteArrayTag toNative(ByteArrayTag tag) { + return new net.minecraft.nbt.ByteArrayTag(tag.getValue().clone()); } - public static net.minecraft.nbt.NbtCompound toNative(CompoundTag tag) { - net.minecraft.nbt.NbtCompound compound = new net.minecraft.nbt.NbtCompound(); + 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()) { compound.put(child.getKey(), toNative(child.getValue())); } return compound; } - public static net.minecraft.nbt.NbtFloat toNative(FloatTag tag) { - return net.minecraft.nbt.NbtFloat.of(tag.getValue()); + public static net.minecraft.nbt.FloatTag toNative(FloatTag tag) { + return net.minecraft.nbt.FloatTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtShort toNative(ShortTag tag) { - return net.minecraft.nbt.NbtShort.of(tag.getValue()); + public static net.minecraft.nbt.ShortTag toNative(ShortTag tag) { + return net.minecraft.nbt.ShortTag.valueOf(tag.getValue()); } - public static net.minecraft.nbt.NbtDouble toNative(DoubleTag tag) { - return net.minecraft.nbt.NbtDouble.of(tag.getValue()); + public static net.minecraft.nbt.DoubleTag toNative(DoubleTag tag) { + return net.minecraft.nbt.DoubleTag.valueOf(tag.getValue()); } - public static Tag fromNative(net.minecraft.nbt.NbtElement other) { - if (other instanceof net.minecraft.nbt.NbtIntArray) { - return fromNative((net.minecraft.nbt.NbtIntArray) other); + public static Tag fromNative(net.minecraft.nbt.Tag other) { + if (other instanceof net.minecraft.nbt.IntArrayTag) { + return fromNative((net.minecraft.nbt.IntArrayTag) other); - } else if (other instanceof net.minecraft.nbt.NbtList) { - return fromNative((net.minecraft.nbt.NbtList) other); + } else if (other instanceof net.minecraft.nbt.ListTag) { + return fromNative((net.minecraft.nbt.ListTag) other); - } else if (other instanceof net.minecraft.nbt.NbtNull) { - return fromNative((net.minecraft.nbt.NbtNull) other); + } else if (other instanceof net.minecraft.nbt.EndTag) { + return fromNative((net.minecraft.nbt.EndTag) other); - } else if (other instanceof net.minecraft.nbt.NbtLong) { - return fromNative((net.minecraft.nbt.NbtLong) other); + } else if (other instanceof net.minecraft.nbt.LongTag) { + return fromNative((net.minecraft.nbt.LongTag) other); - } else if (other instanceof net.minecraft.nbt.NbtLongArray) { - return fromNative((net.minecraft.nbt.NbtLongArray) other); + } else if (other instanceof net.minecraft.nbt.LongArrayTag) { + return fromNative((net.minecraft.nbt.LongArrayTag) other); - } else if (other instanceof net.minecraft.nbt.NbtString) { - return fromNative((net.minecraft.nbt.NbtString) other); + } else if (other instanceof net.minecraft.nbt.StringTag) { + return fromNative((net.minecraft.nbt.StringTag) other); - } else if (other instanceof net.minecraft.nbt.NbtInt) { - return fromNative((net.minecraft.nbt.NbtInt) other); + } else if (other instanceof net.minecraft.nbt.IntTag) { + return fromNative((net.minecraft.nbt.IntTag) other); - } else if (other instanceof net.minecraft.nbt.NbtByte) { - return fromNative((net.minecraft.nbt.NbtByte) other); + } else if (other instanceof net.minecraft.nbt.ByteTag) { + return fromNative((net.minecraft.nbt.ByteTag) other); - } else if (other instanceof net.minecraft.nbt.NbtByteArray) { - return fromNative((net.minecraft.nbt.NbtByteArray) other); + } else if (other instanceof net.minecraft.nbt.ByteArrayTag) { + return fromNative((net.minecraft.nbt.ByteArrayTag) other); - } else if (other instanceof net.minecraft.nbt.NbtCompound) { - return fromNative((net.minecraft.nbt.NbtCompound) other); + } else if (other instanceof net.minecraft.nbt.CompoundTag) { + return fromNative((net.minecraft.nbt.CompoundTag) other); - } else if (other instanceof net.minecraft.nbt.NbtFloat) { - return fromNative((net.minecraft.nbt.NbtFloat) other); + } else if (other instanceof net.minecraft.nbt.FloatTag) { + return fromNative((net.minecraft.nbt.FloatTag) other); - } else if (other instanceof net.minecraft.nbt.NbtShort) { - return fromNative((net.minecraft.nbt.NbtShort) other); + } else if (other instanceof net.minecraft.nbt.ShortTag) { + return fromNative((net.minecraft.nbt.ShortTag) other); - } else if (other instanceof net.minecraft.nbt.NbtDouble) { - return fromNative((net.minecraft.nbt.NbtDouble) other); + } else if (other instanceof net.minecraft.nbt.DoubleTag) { + return fromNative((net.minecraft.nbt.DoubleTag) other); } else { throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); } } - public static IntArrayTag fromNative(net.minecraft.nbt.NbtIntArray other) { - int[] value = other.getIntArray(); + public static IntArrayTag fromNative(net.minecraft.nbt.IntArrayTag other) { + int[] value = other.getAsIntArray(); return new IntArrayTag(Arrays.copyOf(value, value.length)); } - public static ListTag fromNative(net.minecraft.nbt.NbtList other) { + public static ListTag fromNative(net.minecraft.nbt.ListTag other) { other = other.copy(); List list = new ArrayList<>(); Class listClass = StringTag.class; @@ -213,36 +213,36 @@ public static ListTag fromNative(net.minecraft.nbt.NbtList other) { return new ListTag(listClass, list); } - public static EndTag fromNative(net.minecraft.nbt.NbtNull other) { + public static EndTag fromNative(net.minecraft.nbt.EndTag other) { return new EndTag(); } - public static LongTag fromNative(net.minecraft.nbt.NbtLong other) { - return new LongTag(other.longValue()); + public static LongTag fromNative(net.minecraft.nbt.LongTag other) { + return new LongTag(other.getAsLong()); } - public static LongArrayTag fromNative(net.minecraft.nbt.NbtLongArray other) { - return new LongArrayTag(other.getLongArray().clone()); + public static LongArrayTag fromNative(net.minecraft.nbt.LongArrayTag other) { + return new LongArrayTag(other.getAsLongArray().clone()); } - public static StringTag fromNative(net.minecraft.nbt.NbtString other) { - return new StringTag(other.asString()); + public static StringTag fromNative(net.minecraft.nbt.StringTag other) { + return new StringTag(other.getAsString()); } - public static IntTag fromNative(net.minecraft.nbt.NbtInt other) { - return new IntTag(other.intValue()); + public static IntTag fromNative(net.minecraft.nbt.IntTag other) { + return new IntTag(other.getAsInt()); } - public static ByteTag fromNative(net.minecraft.nbt.NbtByte other) { - return new ByteTag(other.byteValue()); + public static ByteTag fromNative(net.minecraft.nbt.ByteTag other) { + return new ByteTag(other.getAsByte()); } - public static ByteArrayTag fromNative(net.minecraft.nbt.NbtByteArray other) { - return new ByteArrayTag(other.getByteArray().clone()); + public static ByteArrayTag fromNative(net.minecraft.nbt.ByteArrayTag other) { + return new ByteArrayTag(other.getAsByteArray().clone()); } - public static CompoundTag fromNative(net.minecraft.nbt.NbtCompound other) { - Set tags = other.getKeys(); + public static CompoundTag fromNative(net.minecraft.nbt.CompoundTag other) { + Set tags = other.getAllKeys(); Map map = new HashMap<>(); for (String tagName : tags) { map.put(tagName, fromNative(other.get(tagName))); @@ -250,16 +250,16 @@ public static CompoundTag fromNative(net.minecraft.nbt.NbtCompound other) { return new CompoundTag(map); } - public static FloatTag fromNative(net.minecraft.nbt.NbtFloat other) { - return new FloatTag(other.floatValue()); + public static FloatTag fromNative(net.minecraft.nbt.FloatTag other) { + return new FloatTag(other.getAsFloat()); } - public static ShortTag fromNative(net.minecraft.nbt.NbtShort other) { - return new ShortTag(other.shortValue()); + public static ShortTag fromNative(net.minecraft.nbt.ShortTag other) { + return new ShortTag(other.getAsShort()); } - public static DoubleTag fromNative(net.minecraft.nbt.NbtDouble other) { - return new DoubleTag(other.doubleValue()); + public static DoubleTag fromNative(net.minecraft.nbt.DoubleTag other) { + return new DoubleTag(other.getAsDouble()); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/PropertyAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/PropertyAdapter.java index 34d40e4e3..32271ee74 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/PropertyAdapter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/PropertyAdapter.java @@ -29,12 +29,12 @@ class PropertyAdapter> implements Property { - private final net.minecraft.state.property.Property property; + private final net.minecraft.world.level.block.state.properties.Property property; private final List values; - public PropertyAdapter(net.minecraft.state.property.Property property) { + public PropertyAdapter(net.minecraft.world.level.block.state.properties.Property property) { this.property = property; - this.values = ImmutableList.copyOf(property.getValues()); + this.values = ImmutableList.copyOf(property.getPossibleValues()); } @Override @@ -49,7 +49,7 @@ public List getValues() { @Override public T getValueFor(String string) throws IllegalArgumentException { - Optional val = property.parse(string); + Optional val = property.getValue(string); checkArgument(val.isPresent(), "%s has no value for %s", getName(), string); return val.get(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientSettingsC2SPacket.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientSettingsC2SPacket.java deleted file mode 100644 index 2aa827716..000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientSettingsC2SPacket.java +++ /dev/null @@ -1,32 +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.fabric.mixin; - -import net.minecraft.network.packet.c2s.play.ClientSettingsC2SPacket; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ClientSettingsC2SPacket.class) -public interface AccessorClientSettingsC2SPacket { - - @Accessor - String getLanguage(); - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java new file mode 100644 index 000000000..b310195f4 --- /dev/null +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java @@ -0,0 +1,16 @@ +package com.sk89q.worldedit.fabric.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ClientboundBlockEntityDataPacket.class) +public interface AccessorClientboundBlockEntityDataPacket { + @Invoker("") + static ClientboundBlockEntityDataPacket construct(BlockPos pos, BlockEntityType blockEntityType, CompoundTag compoundTag) { + throw new AssertionError("This is replaced by Mixin to call the constructor."); + } +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorLevelProperties.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorPrimaryLevelData.java similarity index 76% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorLevelProperties.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorPrimaryLevelData.java index 98fb1c96f..fd51ac5ee 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorLevelProperties.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorPrimaryLevelData.java @@ -19,18 +19,18 @@ package com.sk89q.worldedit.fabric.mixin; -import net.minecraft.world.SaveProperties; -import net.minecraft.world.gen.GeneratorOptions; -import net.minecraft.world.level.LevelProperties; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.storage.PrimaryLevelData; +import net.minecraft.world.level.storage.WorldData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(LevelProperties.class) -public interface AccessorLevelProperties extends SaveProperties { +@Mixin(PrimaryLevelData.class) +public interface AccessorPrimaryLevelData extends WorldData { @Accessor @Mutable - void setGeneratorOptions(GeneratorOptions options); + void setWorldGenSettings(WorldGenSettings options); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkManager.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java similarity index 66% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkManager.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java index 0ef033a8b..3f66ded29 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkManager.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java @@ -20,23 +20,24 @@ package com.sk89q.worldedit.fabric.mixin; import com.mojang.datafixers.util.Either; -import net.minecraft.server.world.ChunkHolder; -import net.minecraft.server.world.ServerChunkManager; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.ChunkStatus; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import java.util.concurrent.CompletableFuture; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.util.thread.BlockableEventLoop; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; -@Mixin(ServerChunkManager.class) -public interface AccessorServerChunkManager { +@Mixin(ServerChunkCache.class) +public interface AccessorServerChunkCache { @Invoker - CompletableFuture> callGetChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); + CompletableFuture> callGetChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); @Accessor - ServerChunkManager.MainThreadExecutor getMainThreadExecutor(); + ServerChunkCache.MainThreadExecutor getMainThreadProcessor(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinBiomeArray.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinBiomeArray.java deleted file mode 100644 index 59d220cda..000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinBiomeArray.java +++ /dev/null @@ -1,49 +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.fabric.mixin; - -import com.sk89q.worldedit.fabric.MutableBiomeArray; -import com.sk89q.worldedit.internal.util.BiomeMath; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.BiomeArray; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(BiomeArray.class) -public abstract class MixinBiomeArray implements MutableBiomeArray { - - @Final - @Shadow - private Biome[] data; - - @Final - @Shadow - private int field_28126; // minY - - @Final - @Shadow - private int field_28127; // maxY - - @Override - public void setBiome(int x, int y, int z, Biome biome) { - this.data[BiomeMath.computeBiomeIndex(x, y, z, field_28126, field_28127)] = biome; - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinWorldChunkSetBlockHook.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java similarity index 58% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinWorldChunkSetBlockHook.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java index 8ca23072c..e873dd217 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinWorldChunkSetBlockHook.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java @@ -20,12 +20,20 @@ package com.sk89q.worldedit.fabric.mixin; import com.sk89q.worldedit.fabric.internal.ExtendedChunk; -import net.minecraft.block.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.UpgradeData; +import net.minecraft.world.level.levelgen.blending.BlendingData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -34,10 +42,14 @@ import javax.annotation.Nullable; -@Mixin(WorldChunk.class) -public abstract class MixinWorldChunkSetBlockHook implements Chunk, ExtendedChunk { +@Mixin(LevelChunk.class) +public abstract class MixinLevelChunkSetBlockHook extends ChunkAccess implements ExtendedChunk { private boolean shouldUpdate = true; + public MixinLevelChunkSetBlockHook(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry registry, long l, @org.jetbrains.annotations.Nullable LevelChunkSection[] levelChunkSections, @org.jetbrains.annotations.Nullable BlendingData blendingData) { + super(chunkPos, upgradeData, levelHeightAccessor, registry, l, levelChunkSections, blendingData); + } + @Nullable @Override public BlockState setBlockState(BlockPos pos, BlockState state, boolean moved, boolean update) { @@ -54,14 +66,14 @@ public BlockState setBlockState(BlockPos pos, BlockState state, boolean moved, b @Redirect( method = "setBlockState", slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/block/AbstractBlock$AbstractBlockState;isOf(Lnet/minecraft/block/Block;)Z") + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/world/level/block/Block;)Z") ), - at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onBlockAdded(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)V", ordinal = 0) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;onPlace(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Z)V") ) - public void setBlockStateHook(BlockState target, World world, BlockPos pos, BlockState old, boolean move) { + public void setBlockStateHook(BlockState target, Level world, BlockPos pos, BlockState old, boolean move) { boolean localShouldUpdate; MinecraftServer server = world.getServer(); - if (server == null || Thread.currentThread() != server.getThread()) { + if (server == null || Thread.currentThread() != server.getRunningThread()) { // We're not on the server thread for some reason, WorldEdit will never be here // so we'll just ignore our flag localShouldUpdate = true; @@ -69,7 +81,7 @@ public void setBlockStateHook(BlockState target, World world, BlockPos pos, Bloc localShouldUpdate = shouldUpdate; } if (localShouldUpdate) { - target.onBlockAdded(world, pos, old, move); + target.onPlace(world, pos, old, move); } } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java index 26f7b9759..806757894 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java @@ -21,11 +21,11 @@ import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.fabric.internal.ExtendedMinecraftServer; -import net.minecraft.resource.ServerResourceManager; +import net.minecraft.Util; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Util; -import net.minecraft.world.World; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.server.ServerResources; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -37,22 +37,22 @@ public abstract class MixinMinecraftServer implements Watchdog, ExtendedMinecraftServer { @Shadow - private long timeReference; + private long nextTickTime; @Final @Shadow - protected LevelStorage.Session session; + protected LevelStorageSource.LevelStorageAccess storageSource; @Override public void tick() { - timeReference = Util.getMeasuringTimeMs(); + nextTickTime = Util.getMillis(); } @Override - public Path getStoragePath(World world) { - return session.getWorldDirectory(world.getRegistryKey()).toPath(); + public Path getStoragePath(Level world) { + return storageSource.getDimensionPath(world.dimension()).toPath(); } - @Accessor() + @Accessor @Override - public abstract ServerResourceManager getServerResourceManager(); + public abstract ServerResources getResources(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayer.java similarity index 72% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayer.java index 3cbf1ad7b..9c5c2adaf 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayerEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerPlayer.java @@ -20,22 +20,22 @@ package com.sk89q.worldedit.fabric.mixin; import com.sk89q.worldedit.fabric.internal.ExtendedPlayerEntity; -import net.minecraft.network.packet.c2s.play.ClientSettingsC2SPacket; -import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(ServerPlayerEntity.class) -public abstract class MixinServerPlayerEntity implements ExtendedPlayerEntity { +@Mixin(ServerPlayer.class) +public abstract class MixinServerPlayer implements ExtendedPlayerEntity { private String language = "en_us"; - @Inject(method = "setClientSettings", at = @At(value = "HEAD")) - public void setClientSettings(ClientSettingsC2SPacket clientSettingsC2SPacket, + @Inject(method = "updateOptions", at = @At(value = "HEAD")) + public void updateOptions(ServerboundClientInformationPacket clientSettingsC2SPacket, CallbackInfo callbackInfo) { - this.language = ((AccessorClientSettingsC2SPacket) clientSettingsC2SPacket).getLanguage(); + this.language = clientSettingsC2SPacket.language(); } @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java index 089b9529b..5e2891e22 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java @@ -24,15 +24,14 @@ import com.sk89q.worldedit.fabric.FabricPlayer; import com.sk89q.worldedit.fabric.FabricWorldEdit; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.util.Identifier; - +import net.minecraft.resources.ResourceLocation; import java.nio.charset.StandardCharsets; public final class WECUIPacketHandler { private WECUIPacketHandler() { } - public static final Identifier CUI_IDENTIFIER = new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL); + public static final ResourceLocation CUI_IDENTIFIER = new ResourceLocation(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL); public static void init() { ServerPlayNetworking.registerGlobalReceiver(CUI_IDENTIFIER, (server, player, handler, buf, responder) -> { diff --git a/worldedit-fabric/src/main/resources/worldedit.accesswidener b/worldedit-fabric/src/main/resources/worldedit.accesswidener new file mode 100644 index 000000000..f2f944ad0 --- /dev/null +++ b/worldedit-fabric/src/main/resources/worldedit.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 named +accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor diff --git a/worldedit-fabric/src/main/resources/worldedit.mixins.json b/worldedit-fabric/src/main/resources/worldedit.mixins.json index e58972154..37f3c7809 100644 --- a/worldedit-fabric/src/main/resources/worldedit.mixins.json +++ b/worldedit-fabric/src/main/resources/worldedit.mixins.json @@ -3,13 +3,12 @@ "package": "com.sk89q.worldedit.fabric.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinBiomeArray", - "MixinServerPlayerEntity", + "AccessorClientboundBlockEntityDataPacket", + "AccessorPrimaryLevelData", + "AccessorServerChunkCache", + "MixinLevelChunkSetBlockHook", "MixinMinecraftServer", - "MixinWorldChunkSetBlockHook", - "AccessorClientSettingsC2SPacket", - "AccessorLevelProperties", - "AccessorServerChunkManager" + "MixinServerPlayer" ], "plugin": "com.sk89q.worldedit.fabric.internal.MixinConfigPlugin", "server": [ diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index 2c5343b02..a7c8ee643 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -8,7 +8,7 @@ `java-library` } -applyPlatformAndCoreConfiguration() +applyPlatformAndCoreConfiguration(javaRelease = 16) applyShadowConfiguration() val minecraftVersion = "1.17.1" From 53559192b456ac2b7827e3fd5f0751e85ba487ae Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 14 Nov 2021 00:15:22 -0800 Subject: [PATCH 03/30] Fix the build a bit Improved checkstyling --- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 2 +- worldedit-core/doctools/build.gradle.kts | 2 +- .../main/java/com/sk89q/jnbt/CompoundTag.java | 2 +- .../src/main/java/com/sk89q/jnbt/ListTag.java | 2 +- .../worldedit/command/tool/BlockTool.java | 5 +-- .../command/tool/DoubleActionBlockTool.java | 5 +-- .../com/sk89q/worldedit/entity/Player.java | 3 +- .../worldedit/util/asset/AssetLoaders.java | 3 +- .../worldedit/fabric/CommandWrapper.java | 6 +-- .../sk89q/worldedit/fabric/FabricAdapter.java | 43 ++++++++++++------- .../fabric/FabricBlockCategoryRegistry.java | 7 +-- .../worldedit/fabric/FabricBlockMaterial.java | 3 +- .../worldedit/fabric/FabricBlockRegistry.java | 3 +- .../sk89q/worldedit/fabric/FabricEntity.java | 5 ++- .../fabric/FabricItemCategoryRegistry.java | 7 +-- .../worldedit/fabric/FabricPlatform.java | 2 +- .../sk89q/worldedit/fabric/FabricPlayer.java | 2 +- .../sk89q/worldedit/fabric/FabricWorld.java | 1 + .../worldedit/fabric/ThreadSafeCache.java | 1 + .../worldedit/fabric/WorldEditFakePlayer.java | 3 +- .../fabric/WorldEditGenListener.java | 1 + .../fabric/internal/ExtendedChunk.java | 3 +- .../internal/ExtendedMinecraftServer.java | 3 +- .../fabric/internal/FabricTransmogrifier.java | 9 ++-- .../internal/FabricWorldNativeAccess.java | 8 ++-- ...essorClientboundBlockEntityDataPacket.java | 19 ++++++++ .../mixin/AccessorServerChunkCache.java | 9 ++-- .../mixin/MixinLevelChunkSetBlockHook.java | 2 - .../net/handler/WECUIPacketHandler.java | 1 + 29 files changed, 100 insertions(+), 62 deletions(-) diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index c4b652888..9fcc25bc5 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -33,7 +33,7 @@ configure { configFile = rootProject.file("config/checkstyle/checkstyle.xml") - toolVersion = "8.34" + toolVersion = "9.1" } tasks.withType().configureEach { diff --git a/worldedit-core/doctools/build.gradle.kts b/worldedit-core/doctools/build.gradle.kts index 7f667b4bc..fb031c1bb 100644 --- a/worldedit-core/doctools/build.gradle.kts +++ b/worldedit-core/doctools/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.4.21" + kotlin("jvm") version "1.5.30" application } 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 3a382effe..e3c75d20c 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/CompoundTag.java @@ -299,8 +299,8 @@ public ListTag getListTag(String key) { * * @param key the key * @param listType the class of the contained type - * @return a list of tags * @param the type of list + * @return a list of tags */ @SuppressWarnings("unchecked") public List getList(String key, Class listType) { 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 8134a3f74..35f6518e0 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/ListTag.java @@ -308,8 +308,8 @@ public ListTag getListTag(int index) { * * @param index the index * @param listType the class of the contained type - * @return a list of tags * @param the NBT type + * @return a list of tags */ @SuppressWarnings("unchecked") public List getList(int index, Class listType) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java index 1579bb37e..a1c17c19c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java @@ -36,9 +36,8 @@ public interface BlockTool extends Tool { * Perform the primary action of this tool. * * @return true to cancel the original event which triggered this action (if possible) - * @deprecated New subclasses should override - * {@link #actPrimary(Platform, LocalConfiguration, Player, LocalSession, Location, Direction)} - * instead + * @deprecated New subclasses should override {@link #actPrimary(Platform, LocalConfiguration, Player, LocalSession, + * Location, Direction)} instead */ @Deprecated default boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java index 7efca8220..6b5abdf58 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java @@ -39,9 +39,8 @@ public interface DoubleActionBlockTool extends BlockTool { * Perform the secondary action of this block tool. * * @return true to cancel the original event which triggered this action (if possible) - * @deprecated New subclasses must override - * {@link #actSecondary(Platform, LocalConfiguration, Player, LocalSession, Location, Direction)} - * instead + * @deprecated New subclasses must override {@link #actSecondary(Platform, LocalConfiguration, Player, LocalSession, + * Location, Direction)} instead */ @Deprecated default boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { 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 2e66eb3a3..da435da12 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 @@ -284,8 +284,7 @@ default Location getBlockIn() { * @param pos where to move them * @param pitch the pitch (up/down) of the player's view in degrees * @param yaw the yaw (left/right) of the player's view in degrees - * @deprecated This method may fail without indication. Use - * {@link #trySetPosition(Vector3, float, float)} instead + * @deprecated This method may fail without indication. Use {@link #trySetPosition(Vector3, float, float)} instead */ @Deprecated default void setPosition(Vector3 pos, float pitch, float yaw) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/asset/AssetLoaders.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/asset/AssetLoaders.java index 3aedd4ed3..249a443fd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/asset/AssetLoaders.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/asset/AssetLoaders.java @@ -132,9 +132,8 @@ public Optional> getAssetLoader(Class assetClass, String f * Get the Asset Loaders for the given type. * * @param assetClass The class to get the loaders of - * @return The list of asset loaders - * * @param The asset type + * @return The list of asset loaders */ @SuppressWarnings("unchecked") public List> getAssetLoaders(Class assetClass) { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java index ebdd2f68a..bfd46c6c1 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java @@ -34,6 +34,9 @@ import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.util.Substring; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.MapBackedValueStore; @@ -42,9 +45,6 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer; import static net.minecraft.commands.Commands.argument; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java index c6d6edb6c..234382a76 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java @@ -37,11 +37,6 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; -import java.util.Comparator; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; -import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; @@ -54,6 +49,12 @@ import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.phys.Vec3; +import java.util.Comparator; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkNotNull; public final class FabricAdapter { @@ -109,11 +110,16 @@ public static Vec3 toVec3(BlockVector3 vector) { public 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 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; @@ -125,11 +131,16 @@ public static Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction f return null; } switch (face) { - case NORTH: return Direction.NORTH; - case SOUTH: return Direction.SOUTH; - case WEST: return Direction.WEST; - case EAST: return Direction.EAST; - case DOWN: return Direction.DOWN; + case NORTH: + return Direction.NORTH; + case SOUTH: + return Direction.SOUTH; + case WEST: + return Direction.WEST; + case EAST: + return Direction.EAST; + case DOWN: + return Direction.DOWN; case UP: default: return Direction.UP; @@ -142,6 +153,7 @@ public static BlockPos toBlockPos(BlockVector3 vector) { /** * Adapts property. + * * @deprecated without replacement, use the block adapter methods */ @Deprecated @@ -151,6 +163,7 @@ public static Property adaptProperty(net.minecraft.world.level.block.state.pr /** * Adapts properties. + * * @deprecated without replacement, use the block adapter methods */ @Deprecated diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java index 39dddea16..b9d9c0641 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java @@ -21,13 +21,14 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.Tag; + import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.BlockTags; -import net.minecraft.tags.Tag; public class FabricBlockCategoryRegistry implements BlockCategoryRegistry { @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java index b4fa668f7..7465a916c 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java @@ -21,11 +21,12 @@ import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.PassthroughBlockMaterial; -import javax.annotation.Nullable; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.PushReaction; +import javax.annotation.Nullable; + /** * Fabric block material that pulls as much info as possible from the Minecraft * Material, and passes the rest to another implementation, typically the diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java index cd6a771ea..227d71088 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java @@ -27,12 +27,13 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.BundledBlockRegistry; +import net.minecraft.world.level.block.Block; + import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.OptionalInt; import java.util.TreeMap; -import net.minecraft.world.level.block.Block; public class FabricBlockRegistry extends BundledBlockRegistry { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java index 4293ba128..4e915f9c9 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java @@ -28,12 +28,13 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.entity.EntityTypes; -import java.lang.ref.WeakReference; -import javax.annotation.Nullable; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; +import java.lang.ref.WeakReference; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkNotNull; class FabricEntity implements Entity { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java index 43d0bc72c..b71ed33d8 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java @@ -21,13 +21,14 @@ import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.Tag; + import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.tags.Tag; public class FabricItemCategoryRegistry implements ItemCategoryRegistry { @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index 5cfb220a6..338329467 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -45,7 +45,6 @@ import net.minecraft.world.level.storage.ServerLevelData; import org.enginehub.piston.CommandManager; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -55,6 +54,7 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; +import javax.annotation.Nullable; class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 09db25a25..04c19c373 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -59,10 +59,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntityType; -import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.UUID; +import javax.annotation.Nullable; public class FabricPlayer extends AbstractPlayerActor { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index 851dacd2d..987389b1b 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -98,6 +98,7 @@ import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; + import java.lang.ref.WeakReference; import java.nio.file.Files; import java.nio.file.Path; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java index e9408e2bf..d76933431 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java @@ -22,6 +22,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; + import java.util.HashSet; import java.util.Set; import java.util.UUID; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java index ef19f5247..aa62955b2 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditFakePlayer.java @@ -20,13 +20,14 @@ package com.sk89q.worldedit.fabric; import com.mojang.authlib.GameProfile; -import java.util.UUID; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.damagesource.DamageSource; +import java.util.UUID; + public class WorldEditFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java index b069d1a95..3cbd70ffe 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/WorldEditGenListener.java @@ -24,6 +24,7 @@ import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkStatus; + import javax.annotation.Nullable; // For now, this does nothing, but might be useful later for regen progress communication. diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java index b89e4157d..2f0d62dc4 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedChunk.java @@ -20,11 +20,12 @@ package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.util.SideEffect; -import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; +import javax.annotation.Nullable; + public interface ExtendedChunk { /** * {@link ChunkAccess#setBlockState(BlockPos, BlockState, boolean)} with the extra diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java index ebb801c54..0a476fffd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ExtendedMinecraftServer.java @@ -19,10 +19,11 @@ package com.sk89q.worldedit.fabric.internal; -import java.nio.file.Path; import net.minecraft.server.ServerResources; import net.minecraft.world.level.Level; +import java.nio.file.Path; + public interface ExtendedMinecraftServer { Path getStoragePath(Level world); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java index 224e4e5d4..fec99ee38 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java @@ -28,16 +28,17 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.block.BlockType; -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; -import java.util.stream.Collectors; import net.minecraft.util.StringRepresentable; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.DirectionProperty; +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + /** * Raw, un-cached transformations. */ diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java index ea20ce60d..2719a9a7e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java @@ -24,10 +24,6 @@ import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.world.storage.ChunkStore; -import java.lang.ref.WeakReference; -import java.util.Objects; -import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ChunkHolder; @@ -38,6 +34,10 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import java.lang.ref.WeakReference; +import java.util.Objects; +import javax.annotation.Nullable; + public class FabricWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; private static final int NOTIFY = 2; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java index b310195f4..3c25e346b 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorClientboundBlockEntityDataPacket.java @@ -1,3 +1,22 @@ +/* + * 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.fabric.mixin; import net.minecraft.core.BlockPos; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java index 3f66ded29..e19ab0f68 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/AccessorServerChunkCache.java @@ -20,16 +20,15 @@ package com.sk89q.worldedit.fabric.mixin; import com.mojang.datafixers.util.Either; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import java.util.concurrent.CompletableFuture; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.util.thread.BlockableEventLoop; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; @Mixin(ServerChunkCache.class) public interface AccessorServerChunkCache { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java index e873dd217..6c0ef09cd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinLevelChunkSetBlockHook.java @@ -27,14 +27,12 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.blending.BlendingData; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java index 5e2891e22..888174e0f 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.fabric.FabricWorldEdit; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.resources.ResourceLocation; + import java.nio.charset.StandardCharsets; public final class WECUIPacketHandler { From 953e22fc38e91bb87fa1afdba7b8d5d506e6fa54 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Thu, 18 Nov 2021 12:16:26 -0800 Subject: [PATCH 04/30] [Fabric] Update to 1.18-pre4 --- buildSrc/src/main/kotlin/CommonConfig.kt | 2 +- worldedit-fabric/build.gradle.kts | 8 ++++---- .../worldedit/fabric/mixin/MixinMinecraftServer.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt index 8701c8716..3159aec3f 100644 --- a/buildSrc/src/main/kotlin/CommonConfig.kt +++ b/buildSrc/src/main/kotlin/CommonConfig.kt @@ -26,7 +26,7 @@ plugins.withId("java") { the().toolchain { - languageVersion.set(JavaLanguageVersion.of(16)) + languageVersion.set(JavaLanguageVersion.of(17)) } } diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 060115fc9..8ab00b92a 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -15,14 +15,14 @@ } } -applyPlatformAndCoreConfiguration(javaRelease = 16) +applyPlatformAndCoreConfiguration(javaRelease = 17) applyShadowConfiguration() apply(plugin = "fabric-loom") apply(plugin = "java-library") -val minecraftVersion = "1.18-pre1" -val yarnMappings = "1.18-pre1+build.6:v2" +val minecraftVersion = "1.18-pre4" +val yarnMappings = "1.18-pre3+build.5:v2" val loaderVersion = "0.12.5" val fabricApiConfiguration: Configuration = configurations.create("fabricApi") @@ -49,7 +49,7 @@ "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") // [1] declare fabric-api dependency... - "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.42.2+1.18") + "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.42.7+1.18") // [2] Load the API dependencies from the fabric mod json... @Suppress("UNCHECKED_CAST") diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java index 806757894..17ae3eea9 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java @@ -49,7 +49,7 @@ public void tick() { @Override public Path getStoragePath(Level world) { - return storageSource.getDimensionPath(world.dimension()).toPath(); + return storageSource.getDimensionPath(world.dimension()); } @Accessor From c4074717b3d783317e57f42f20d79d17f8d050de Mon Sep 17 00:00:00 2001 From: wizjany Date: Fri, 19 Nov 2021 14:47:21 -0500 Subject: [PATCH 05/30] Re-add class shutter with tweaks. (#1947) We want to hide default-package classes, such as "com", "io", etc. which are common names in Mojang obf classes but also common package names, without hiding generated default-package classes such as described in #1895. This reverts commit 6008fe73 --- .../MinecraftHidingClassShutter.java | 32 +++++++++++++++++++ .../scripting/RhinoCraftScriptEngine.java | 1 + 2 files changed, 33 insertions(+) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/scripting/MinecraftHidingClassShutter.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/MinecraftHidingClassShutter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/MinecraftHidingClassShutter.java new file mode 100644 index 000000000..8a0e1a16b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/MinecraftHidingClassShutter.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.scripting; + +import org.mozilla.javascript.ClassShutter; + +/** + * Hides Minecraft's obfuscated names from scripts. + */ +class MinecraftHidingClassShutter implements ClassShutter { + @Override + public boolean visibleToScripts(String fullClassName) { + return fullClassName.contains(".") || fullClassName.length() >= 4; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java index d4f49ded8..ee9e65afd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java @@ -48,6 +48,7 @@ public int getTimeLimit() { public Object evaluate(String script, String filename, Map args) throws Throwable { RhinoContextFactory factory = new RhinoContextFactory(timeLimit); Context cx = factory.enterContext(); + cx.setClassShutter(new MinecraftHidingClassShutter()); ScriptableObject scriptable = new ImporterTopLevel(cx); Scriptable scope = cx.initStandardObjects(scriptable); From 29f1c661571a3bbdb96fbf50eb6dfb80a30c6aea Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sat, 20 Nov 2021 18:13:45 -0800 Subject: [PATCH 06/30] If a trace hits the world limit, cancel it (#1942) --- .../java/com/sk89q/worldedit/util/TargetBlock.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) 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 62a2d1875..f6e52e616 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 @@ -143,18 +143,15 @@ private void setValues(Vector3 loc, double rotationX, double rotationY, int maxD * @return Block */ public Location getAnyTargetBlock() { - boolean searchForLastBlock = true; Location lastBlock = null; while (getNextBlock() != null) { if (stopMask.test(targetPos)) { break; } else { - if (searchForLastBlock) { - lastBlock = getCurrentBlock(); - if (lastBlock.getBlockY() <= world.getMinY() - || lastBlock.getBlockY() >= world.getMaxY()) { - searchForLastBlock = false; - } + lastBlock = getCurrentBlock(); + if (lastBlock.getBlockY() < world.getMinY() + || lastBlock.getBlockY() > world.getMaxY()) { + return null; } } } From 511daa507894f761888e14a7837511a2bcafd92a Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Tue, 23 Nov 2021 17:25:28 -0800 Subject: [PATCH 07/30] Update paperweight dev bundle --- worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts index a5c997534..4609231c3 100644 --- a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts @@ -1,3 +1,3 @@ applyPaperweightAdapterConfiguration( - "1.17.1-R0.1-20211109.085555-183" + "1.17.1-R0.1-20211120.192557-194" ) From 1aad921836e58abf6847266bb116df62c2ee407f Mon Sep 17 00:00:00 2001 From: wizjany Date: Thu, 25 Nov 2021 11:21:15 -0500 Subject: [PATCH 08/30] Bump paperlib dep. Fixes a bug with detecting pre-release versions. --- worldedit-bukkit/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index daa355989..f5fe1cd68 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -55,7 +55,7 @@ "compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") { exclude(group = "org.slf4j", module = "slf4j-api") } - "implementation"("io.papermc:paperlib:1.0.6") + "implementation"("io.papermc:paperlib:1.0.7") "compileOnly"("com.sk89q:dummypermscompat:1.10") "implementation"("org.bstats:bstats-bukkit:2.1.0") "implementation"("it.unimi.dsi:fastutil") From 44d91b0c73bd8b85490725470f5a82339c56ff88 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Fri, 26 Nov 2021 18:54:34 -0800 Subject: [PATCH 09/30] Shove 1.17 adapters into a jar to fix the build --- buildSrc/build.gradle.kts | 13 +- buildSrc/src/main/kotlin/AdapterConfig.kt | 9 +- settings.gradle.kts | 1 + .../adapters/adapter-1.17.1/build.gradle.kts | 21 +- .../resources/worldedit-adapter-1.17.1.jar | Bin 0 -> 124505 bytes .../adapters/adapter-1.18/build.gradle.kts | 14 + .../impl/v1_18_R1/PaperweightAdapter.java | 1017 ++++++ .../v1_18_R1/PaperweightDataConverters.java | 2795 +++++++++++++++++ .../impl/v1_18_R1/PaperweightFakePlayer.java | 98 + .../PaperweightWorldNativeAccess.java | 182 ++ 10 files changed, 4134 insertions(+), 16 deletions(-) create mode 100644 worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar create mode 100644 worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts create mode 100644 worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java create mode 100644 worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightDataConverters.java create mode 100644 worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightFakePlayer.java create mode 100644 worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightWorldNativeAccess.java diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 1b1b5f79a..b8497813c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -8,10 +8,6 @@ repositories { mavenCentral() gradlePluginPortal() - maven { - name = "PaperMC" - url = uri("https://papermc.io/repo/repository/maven-public/") - } maven { name = "Fabric" url = uri("https://maven.fabricmc.net/") @@ -24,6 +20,13 @@ name = "EngineHub Repository" url = uri("https://maven.enginehub.org/repo/") } + maven { + name = "PaperMC" + url = uri("https://papermc.io/repo/repository/maven-public/") + content { + includeGroupByRegex("io\\.papermc\\..*") + } + } maven { name = "Forge Maven" url = uri("https://maven.minecraftforge.net/") @@ -52,5 +55,5 @@ implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.1.14") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.0-SNAPSHOT") } diff --git a/buildSrc/src/main/kotlin/AdapterConfig.kt b/buildSrc/src/main/kotlin/AdapterConfig.kt index a120038e9..975b76999 100644 --- a/buildSrc/src/main/kotlin/AdapterConfig.kt +++ b/buildSrc/src/main/kotlin/AdapterConfig.kt @@ -1,16 +1,10 @@ -import io.papermc.paperweight.util.constants.REOBF_CONFIG -import io.papermc.paperweight.userdev.attribute.Obfuscation import org.gradle.api.Project import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.named // For specific version pinning, see // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ -fun Project.applyPaperweightAdapterConfiguration( - paperVersion: String -) { +fun Project.applyPaperweightAdapterConfiguration() { applyCommonConfiguration() apply(plugin = "java-library") applyCommonJavaConfiguration( @@ -20,7 +14,6 @@ apply(plugin = "io.papermc.paperweight.userdev") dependencies { - paperDevBundle(paperVersion) "implementation"(project(":worldedit-bukkit")) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 8b077bbde..5cdb7926d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,6 +4,7 @@ include("worldedit-bukkit:adapters:adapter-legacy") include("worldedit-bukkit:adapters:adapter-1.17.1") +include("worldedit-bukkit:adapters:adapter-1.18") listOf("bukkit", "core", "sponge", "fabric", "forge", "cli").forEach { include("worldedit-libs:$it") diff --git a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts index a5c997534..3dcbe3ad6 100644 --- a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts @@ -1,3 +1,18 @@ -applyPaperweightAdapterConfiguration( - "1.17.1-R0.1-20211109.085555-183" -) +// TODO await https://github.com/PaperMC/paperweight/issues/116 +//applyPaperweightAdapterConfiguration() +// +//dependencies { +// paperDevBundle("1.17.1-R0.1-20211120.192557-194") +//} + +// Until the above issue is resolved, we are bundling old versions using their last assembled JAR. +// Technically this means we cannot really update them, but that is is the price we pay for supporting older versions. + +plugins { + base +} + +artifacts { + add("default", file("./src/main/resources/worldedit-adapter-1.17.1.jar")) +} + diff --git a/worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar b/worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..d370dc4e95700f713b3bde2ac2ec12f33feb09e5 GIT binary patch literal 124505 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 diff --git a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts index 2c478b056..3ccca4fe4 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts @@ -2,5 +2,5 @@ dependencies { // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ - paperDevBundle("1.18.1-R0.1-20211212.093039-5") + paperDevBundle("1.18.1-R0.1-20211221.093324-19") }

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 literal 0 HcmV?d00001 diff --git a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts new file mode 100644 index 000000000..8e6b5dd91 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts @@ -0,0 +1,14 @@ +applyPaperweightAdapterConfiguration() + +repositories { + // For now, dev-bundle comes from mavenLocal. + mavenLocal { + content { + includeGroup("io.papermc.paper") + } + } +} + +dependencies { + paperDevBundle("1.18-rc3-R0.1-SNAPSHOT") +} diff --git a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java new file mode 100644 index 000000000..d68615260 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java @@ -0,0 +1,1017 @@ +/* + * 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.impl.v1_18_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.Codec; +import com.mojang.serialization.Dynamic; +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; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +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.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.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.nbt.NbtOps; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; +import net.minecraft.resources.RegistryReadOps; +import net.minecraft.resources.RegistryWriteOps; +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.chunk.PalettedContainer; +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_18_R1.CraftServer; +import org.bukkit.craftbukkit.v1_18_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_18_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 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.HashSet; +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.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 final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + + private final Field serverWorldsField; + private final Method getChunkFutureMethod; + private final Field chunkProviderExecutorField; + 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!"); + } + + serverWorldsField = CraftServer.class.getDeclaredField("worlds"); + serverWorldsField.setAccessible(true); + + getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread", + int.class, int.class, ChunkStatus.class, boolean.class); + getChunkFutureMethod.setAccessible(true); + + chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField( + Refraction.pickName("mainThreadProcessor", "h") + ); + chunkProviderExecutorField.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.worldeditregentempworld.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 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(); + return state.toBaseBlock((CompoundTag) toNative(tag)); + } + + 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); + return new BaseEntity(com.sk89q.worldedit.world.entity.EntityTypes.get(id), (CompoundTag) toNative(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(); + + 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.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" }) + @Override + public Map> getProperties(BlockType blockType) { + Map> properties = Maps.newTreeMap(String::compareTo); + Block block = getBlockFromType(blockType); + StateDefinition blockStateList = + block.getStateDefinition(); + for (net.minecraft.world.level.block.state.properties.Property state : blockStateList.getProperties()) { + Property property; + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + property = new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + property = 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) { + property = 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) { + property = new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); + } + + properties.put(property.getName(), property); + } + return properties; + } + + @Override + public void sendFakeNBT(Player player, BlockVector3 pos, CompoundTag 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) fromNative(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.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("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(); + WorldGenSettings originalOpts = levelProperties.worldGenSettings(); + + long seed = options.getSeed().orElse(originalWorld.getSeed()); + WorldGenSettings newOpts = options.getSeed().isPresent() + ? replaceSeed(originalWorld, seed, originalOpts) + : originalOpts; + + LevelSettings newWorldSettings = new LevelSettings( + "worldeditregentempworld", + 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) serverWorldsField.get(Bukkit.getServer()); + map.remove("worldeditregentempworld"); + } catch (IllegalAccessException ignored) { + } + SafeFiles.tryHardToDeleteDir(tempDir); + } + } + + private WorldGenSettings replaceSeed(ServerLevel originalWorld, long seed, WorldGenSettings originalOpts) { + RegistryWriteOps nbtReadRegOps = RegistryWriteOps.create( + NbtOps.INSTANCE, + originalWorld.getServer().registryAccess() + ); + RegistryReadOps nbtRegOps = RegistryReadOps.createAndLoad( + NbtOps.INSTANCE, + originalWorld.getServer().getResourceManager(), + originalWorld.getServer().registryAccess() + ); + Codec dimCodec = WorldGenSettings.CODEC; + return dimCodec + .encodeStart(nbtReadRegOps, originalOpts) + .flatMap(tag -> + dimCodec.parse( + recursivelySetSeed(new Dynamic<>(nbtRegOps, tag), seed, new HashSet<>()) + ) + ) + .get() + .map( + l -> l, + error -> { + throw new IllegalStateException("Unable to map GeneratorOptions: " + error.message()); + } + ); + } + + @SuppressWarnings("unchecked") + private Dynamic recursivelySetSeed(Dynamic dynamic, long seed, Set> seen) { + if (!seen.add(dynamic)) { + return dynamic; + } + return dynamic.updateMapValues(pair -> { + if (pair.getFirst().asString("").equals("seed")) { + return pair.mapSecond(v -> v.createLong(seed)); + } + if (pair.getSecond().getValue() instanceof net.minecraft.nbt.CompoundTag) { + return pair.mapSecond(v -> recursivelySetSeed((Dynamic) v, seed, seen)); + } + return pair; + }); + } + + 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) 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.getBlockX(), vec.getBlockY(), vec.getBlockZ()); + 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(); + state = state.toBaseBlock(((CompoundTag) toNative(tag))); + } + extent.setBlock(vec, state.toBaseBlock()); + if (options.shouldRegenBiomes()) { + PalettedContainer biomeIndex = chunk.getSection(chunk.getSectionIndex(vec.getBlockY())) + .getBiomes(); + Biome origBiome = biomeIndex.get(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 { + //noinspection unchecked + chunkLoadings.add( + ((CompletableFuture>) + getChunkFutureMethod.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 + */ + Tag toNative(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, toNative(base)); + } + return new CompoundTag(values); + } else if (foreign instanceof net.minecraft.nbt.ByteTag) { + return new ByteTag(((net.minecraft.nbt.ByteTag) foreign).getAsByte()); + } else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) { + return new ByteArrayTag(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray()); + } else if (foreign instanceof net.minecraft.nbt.DoubleTag) { + return new DoubleTag(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble()); + } else if (foreign instanceof net.minecraft.nbt.FloatTag) { + return new FloatTag(((net.minecraft.nbt.FloatTag) foreign).getAsFloat()); + } else if (foreign instanceof net.minecraft.nbt.IntTag) { + return new IntTag(((net.minecraft.nbt.IntTag) foreign).getAsInt()); + } else if (foreign instanceof net.minecraft.nbt.IntArrayTag) { + return new IntArrayTag(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray()); + } else if (foreign instanceof net.minecraft.nbt.LongArrayTag) { + return new LongArrayTag(((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 new ListTag(ByteTag.class, new ArrayList()); + } + } else if (foreign instanceof net.minecraft.nbt.LongTag) { + return new LongTag(((net.minecraft.nbt.LongTag) foreign).getAsLong()); + } else if (foreign instanceof net.minecraft.nbt.ShortTag) { + return new ShortTag(((net.minecraft.nbt.ShortTag) foreign).getAsShort()); + } else if (foreign instanceof net.minecraft.nbt.StringTag) { + return new StringTag(foreign.getAsString()); + } else if (foreign instanceof net.minecraft.nbt.EndTag) { + return new EndTag(); + } 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 ListTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { + List values = new ArrayList<>(); + int type = foreign.getElementType(); + + for (net.minecraft.nbt.Tag tag : foreign) { + values.add(toNative(tag)); + } + + Class cls = NBTConstants.getClassFromType(type); + return new ListTag(cls, values); + } + + /** + * Converts a WorldEdit-native NBT structure to a NMS structure. + * + * @param foreign structure to convert + * @return non-native structure + */ + net.minecraft.nbt.Tag fromNative(Tag foreign) { + if (foreign == null) { + return null; + } + if (foreign instanceof CompoundTag) { + net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + for (Map.Entry entry : ((CompoundTag) foreign) + .getValue().entrySet()) { + tag.put(entry.getKey(), fromNative(entry.getValue())); + } + return tag; + } else if (foreign instanceof ByteTag) { + return net.minecraft.nbt.ByteTag.valueOf(((ByteTag) foreign).getValue()); + } else if (foreign instanceof ByteArrayTag) { + return new net.minecraft.nbt.ByteArrayTag(((ByteArrayTag) foreign).getValue()); + } else if (foreign instanceof DoubleTag) { + return net.minecraft.nbt.DoubleTag.valueOf(((DoubleTag) foreign).getValue()); + } else if (foreign instanceof FloatTag) { + return net.minecraft.nbt.FloatTag.valueOf(((FloatTag) foreign).getValue()); + } else if (foreign instanceof IntTag) { + return net.minecraft.nbt.IntTag.valueOf(((IntTag) foreign).getValue()); + } else if (foreign instanceof IntArrayTag) { + return new net.minecraft.nbt.IntArrayTag(((IntArrayTag) foreign).getValue()); + } else if (foreign instanceof LongArrayTag) { + return new net.minecraft.nbt.LongArrayTag(((LongArrayTag) foreign).getValue()); + } else if (foreign instanceof ListTag) { + net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); + ListTag foreignList = (ListTag) foreign; + for (Tag t : foreignList.getValue()) { + tag.add(fromNative(t)); + } + return tag; + } else if (foreign instanceof LongTag) { + return net.minecraft.nbt.LongTag.valueOf(((LongTag) foreign).getValue()); + } else if (foreign instanceof ShortTag) { + return net.minecraft.nbt.ShortTag.valueOf(((ShortTag) foreign).getValue()); + } else if (foreign instanceof StringTag) { + return net.minecraft.nbt.StringTag.valueOf(((StringTag) foreign).getValue()); + } else if (foreign instanceof EndTag) { + 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( + 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, @org.jetbrains.annotations.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.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightDataConverters.java new file mode 100644 index 000000000..7d5c4ad79 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightDataConverters.java @@ -0,0 +1,2795 @@ +/* + * 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.impl.v1_18_R1; + +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.jnbt.CompoundTag; +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 { + + @SuppressWarnings("unchecked") + @Override + public T fixUp(FixType type, T original, int srcVer) { + if (type == FixTypes.CHUNK) { + return (T) fixChunk((CompoundTag) original, srcVer); + } else if (type == FixTypes.BLOCK_ENTITY) { + return (T) fixBlockEntity((CompoundTag) original, srcVer); + } else if (type == FixTypes.ENTITY) { + return (T) fixEntity((CompoundTag) 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 CompoundTag fixChunk(CompoundTag originalChunk, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative(originalChunk); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); + return (CompoundTag) adapter.toNative(fixed); + } + + private CompoundTag fixBlockEntity(CompoundTag origTileEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative(origTileEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); + return (CompoundTag) adapter.toNative(fixed); + } + + private CompoundTag fixEntity(CompoundTag origEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative(origEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); + return (CompoundTag) adapter.toNative(fixed); + } + + 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.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightFakePlayer.java new file mode 100644 index 000000000..427c57a59 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightFakePlayer.java @@ -0,0 +1,98 @@ +/* + * 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.impl.v1_18_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.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/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightWorldNativeAccess.java new file mode 100644 index 000000000..276defab7 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightWorldNativeAccess.java @@ -0,0 +1,182 @@ +/* + * 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.impl.v1_18_R1; + +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.world.block.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ChunkHolder; +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_18_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_18_R1.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(BlockPos position, CompoundTag 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.fromNative(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(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); + } +} From 979b52273800fc1f4e57460ce2d56892fbc4a858 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sat, 27 Nov 2021 13:45:05 -0500 Subject: [PATCH 10/30] Make Paperweight adapter run on 1.18rc3. --- .../bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java | 4 ++-- worldedit-bukkit/build.gradle.kts | 2 +- .../src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java index d68615260..b91765df3 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java @@ -186,8 +186,8 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { CraftServer.class.cast(Bukkit.getServer()); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2730) { - throw new UnsupportedClassVersionError("Not 1.17.1!"); + if (dataVersion != 2858) { // 1.18 release should be 2859 + throw new UnsupportedClassVersionError("Not 1.18!"); } serverWorldsField = CraftServer.class.getDeclaredField("worlds"); diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index daa355989..77fb6571d 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -55,7 +55,7 @@ "compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") { exclude(group = "org.slf4j", module = "slf4j-api") } - "implementation"("io.papermc:paperlib:1.0.6") + "implementation"("io.papermc:paperlib:1.0.8-SNAPSHOT") "compileOnly"("com.sk89q:dummypermscompat:1.10") "implementation"("org.bstats:bstats-bukkit:2.1.0") "implementation"("it.unimi.dsi:fastutil") 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 38e152d75..bc25ca4bf 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 @@ -519,7 +519,7 @@ public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { @Override public boolean fullySupports3DBiomes() { // Supports if API does and we're not in the overworld - return HAS_3D_BIOMES && getWorld().getEnvironment() != World.Environment.NORMAL; + return HAS_3D_BIOMES && (getWorld().getEnvironment() != World.Environment.NORMAL || PaperLib.isVersion(18)); } @SuppressWarnings("deprecation") From 6760ad7115660dbafc42d71aca44d42e8306b76b Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 11:53:14 -0500 Subject: [PATCH 11/30] Bump version numbers and stuff for 1.18 release. --- .../adapters/adapter-1.18/build.gradle.kts | 11 +---------- .../adapter/impl/v1_18_R1/PaperweightAdapter.java | 2 +- worldedit-bukkit/build.gradle.kts | 2 +- worldedit-fabric/build.gradle.kts | 8 ++++---- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts index 8e6b5dd91..55690c1a7 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts @@ -1,14 +1,5 @@ applyPaperweightAdapterConfiguration() -repositories { - // For now, dev-bundle comes from mavenLocal. - mavenLocal { - content { - includeGroup("io.papermc.paper") - } - } -} - dependencies { - paperDevBundle("1.18-rc3-R0.1-SNAPSHOT") + paperDevBundle("1.18-R0.1-20211130.164241-2") } diff --git a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java index b91765df3..7aa53b88c 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java @@ -186,7 +186,7 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { CraftServer.class.cast(Bukkit.getServer()); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2858) { // 1.18 release should be 2859 + if (dataVersion != 2860) { throw new UnsupportedClassVersionError("Not 1.18!"); } diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 77fb6571d..f5fe1cd68 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -55,7 +55,7 @@ "compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") { exclude(group = "org.slf4j", module = "slf4j-api") } - "implementation"("io.papermc:paperlib:1.0.8-SNAPSHOT") + "implementation"("io.papermc:paperlib:1.0.7") "compileOnly"("com.sk89q:dummypermscompat:1.10") "implementation"("org.bstats:bstats-bukkit:2.1.0") "implementation"("it.unimi.dsi:fastutil") diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 8ab00b92a..ce0be43bf 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -21,9 +21,9 @@ apply(plugin = "fabric-loom") apply(plugin = "java-library") -val minecraftVersion = "1.18-pre4" -val yarnMappings = "1.18-pre3+build.5:v2" -val loaderVersion = "0.12.5" +val minecraftVersion = "1.18" +val yarnMappings = "1.18+build.1:v2" +val loaderVersion = "0.12.6" val fabricApiConfiguration: Configuration = configurations.create("fabricApi") @@ -49,7 +49,7 @@ "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") // [1] declare fabric-api dependency... - "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.42.7+1.18") + "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.43.1+1.18") // [2] Load the API dependencies from the fabric mod json... @Suppress("UNCHECKED_CAST") From b00e0a4cfb4559c463c0967b64552c02fa1f1b70 Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 13:58:48 -0500 Subject: [PATCH 12/30] Paperweight roulette. --- worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts index 55690c1a7..f75b37a9b 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts @@ -1,5 +1,5 @@ applyPaperweightAdapterConfiguration() dependencies { - paperDevBundle("1.18-R0.1-20211130.164241-2") + paperDevBundle("1.18-R0.1-20211130.173143-6") } From 4e3fa750ec2830cca0a2a2672fe3cbb4cd1e440d Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 14:59:36 -0500 Subject: [PATCH 13/30] Missed mapping. --- .../bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java index 7aa53b88c..713c7d1c0 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java @@ -193,8 +193,10 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); - getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread", - int.class, int.class, ChunkStatus.class, boolean.class); + getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod( + Refraction.pickName("getChunkFutureMainThread", "c"), + int.class, int.class, ChunkStatus.class, boolean.class + ); getChunkFutureMethod.setAccessible(true); chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField( From f534b61f30ebb07c1088fb17f351cce6fe0f22cb Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 16:01:06 -0500 Subject: [PATCH 14/30] Theoretically works on forge. --- buildSrc/build.gradle.kts | 2 +- worldedit-bukkit/build.gradle.kts | 6 -- worldedit-core/build.gradle.kts | 2 +- worldedit-forge/build.gradle.kts | 10 +-- .../sk89q/worldedit/forge/ForgeAdapter.java | 3 +- .../forge/ForgePermissionsProvider.java | 2 +- .../sk89q/worldedit/forge/ForgePlatform.java | 2 +- .../sk89q/worldedit/forge/ForgePlayer.java | 14 ++-- .../com/sk89q/worldedit/forge/ForgeWorld.java | 76 ++++++++----------- .../sk89q/worldedit/forge/ForgeWorldEdit.java | 16 ++-- .../worldedit/forge/ThreadSafeCache.java | 2 +- .../net/handler/InternalPacketHandler.java | 2 +- .../forge/net/handler/PacketHandlerUtil.java | 2 +- .../forge/net/handler/WECUIPacketHandler.java | 4 +- .../net/packet/LeftClickAirEventMessage.java | 2 +- 15 files changed, 63 insertions(+), 82 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b8497813c..ae7a4a392 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -51,7 +51,7 @@ implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.0") implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.24.23") implementation("org.spongepowered:SpongeGradle:0.11.5") - implementation("net.minecraftforge.gradle:ForgeGradle:5.1.14") + implementation("net.minecraftforge.gradle:ForgeGradle:5.1.25") implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index f5fe1cd68..22264c177 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -13,12 +13,6 @@ maven { url = uri("https://papermc.io/repo/repository/maven-public/") } } -configurations.all { - resolutionStrategy { - force("com.google.guava:guava:21.0") - } -} - val localImplementation = configurations.create("localImplementation") { description = "Dependencies used locally, but provided by the runtime Bukkit implementation" isCanBeConsumed = false diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 79b700ed7..8cc793221 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -55,7 +55,7 @@ "compileOnly"(project(":worldedit-libs:core:ap")) "annotationProcessor"(project(":worldedit-libs:core:ap")) // ensure this is on the classpath for the AP - "annotationProcessor"("com.google.guava:guava:21.0") + "annotationProcessor"("com.google.guava:guava:${Versions.GUAVA}") "compileOnly"("com.google.auto.value:auto-value-annotations:${Versions.AUTO_VALUE}") "annotationProcessor"("com.google.auto.value:auto-value:${Versions.AUTO_VALUE}") diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index a7c8ee643..1e19a39b5 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -11,17 +11,11 @@ applyPlatformAndCoreConfiguration(javaRelease = 16) applyShadowConfiguration() -val minecraftVersion = "1.17.1" +val minecraftVersion = "1.18" val nextMajorMinecraftVersion: String = minecraftVersion.split('.').let { (useless, major) -> "$useless.${major.toInt() + 1}" } -val forgeVersion = "37.0.12" - -configurations.all { - resolutionStrategy { - force("com.google.guava:guava:21.0") - } -} +val forgeVersion = "38.0.0" dependencies { "api"(project(":worldedit-core")) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java index 1532dc0c5..b5f323e3d 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java @@ -45,13 +45,12 @@ import net.minecraft.util.StringRepresentable; import net.minecraft.world.item.Item; 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.state.properties.DirectionProperty; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.server.ServerLifecycleHooks; import java.util.Comparator; import java.util.Map; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java index 96e5fb266..cdfe1dae6 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java @@ -21,7 +21,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.GameType; -import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; +import net.minecraftforge.server.ServerLifecycleHooks; public interface ForgePermissionsProvider { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index e1a32e4bc..113245746 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -42,7 +42,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.PlayerList; import net.minecraft.world.level.storage.ServerLevelData; -import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; +import net.minecraftforge.server.ServerLifecycleHooks; import org.enginehub.piston.Command; import org.enginehub.piston.CommandManager; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index eb104c7a0..dbfce5720 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -55,6 +55,8 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.StructureBlockEntity; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.EntityTravelToDimensionEvent; @@ -257,11 +259,13 @@ public > void sendFakeBlock(BlockVector3 pos, B bl final BaseBlock baseBlock = (BaseBlock) block; final CompoundTag nbtData = baseBlock.getNbtData(); if (nbtData != null) { - player.connection.send(new ClientboundBlockEntityDataPacket( - new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - STRUCTURE_BLOCK_PACKET_ID, - NBTConverter.toNative(nbtData)) - ); + player.connection.send(ClientboundBlockEntityDataPacket.create( + new StructureBlockEntity( + new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), + Blocks.STRUCTURE_BLOCK.defaultBlockState() + ), + __ -> NBTConverter.toNative(nbtData) + )); } } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index cf5e65ffb..573a4146d 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -64,7 +64,8 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; -import net.minecraft.data.worldgen.Features; +import net.minecraft.data.worldgen.features.EndFeatures; +import net.minecraft.data.worldgen.features.TreeFeatures; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.resources.RegistryReadOps; @@ -83,13 +84,12 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.BiomeZoomer; -import net.minecraft.world.level.biome.FuzzyOffsetConstantColumnBiomeZoomer; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BlockEntity; 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.chunk.PalettedContainer; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; @@ -176,9 +176,7 @@ public String getId() { @Override public Path getStoragePath() { final ServerLevel world = getWorld(); - return world.getServer().storageSource.getDimensionPath( - world.dimension() - ).toPath(); + return world.getServer().storageSource.getDimensionPath(world.dimension()); } @Override @@ -211,12 +209,6 @@ public boolean clearContainerBlockContents(BlockVector3 position) { return false; } - @Override - public boolean fullySupports3DBiomes() { - BiomeZoomer okZoomer = getWorld().dimensionType().getBiomeZoomer(); - return !(okZoomer instanceof FuzzyOffsetConstantColumnBiomeZoomer); - } - @Override public BiomeType getBiome(BlockVector3 position) { checkNotNull(position); @@ -226,8 +218,7 @@ public BiomeType getBiome(BlockVector3 position) { } private BiomeType getBiomeInChunk(BlockVector3 position, ChunkAccess chunk) { - ChunkBiomeContainer biomes = checkNotNull(chunk.getBiomes()); - return ForgeAdapter.adapt(biomes.getNoiseBiome(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2)); + return ForgeAdapter.adapt(chunk.getNoiseBiome(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2)); } @Override @@ -236,11 +227,11 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { checkNotNull(biome); LevelChunk chunk = getWorld().getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4); - ChunkBiomeContainer container = checkNotNull(chunk.getBiomes()); - int idx = BiomeMath.computeBiomeIndex( - position.getX(), position.getY(), position.getZ(), getMinY(), getMaxY() + PalettedContainer biomes = chunk.getSection(chunk.getSectionIndex(position.getY())).getBiomes(); + biomes.getAndSetUnchecked( + position.getX() & 3, position.getY() & 3, position.getZ() & 3, + ForgeAdapter.adapt(biome) ); - container.biomes[idx] = ForgeAdapter.adapt(biome); chunk.setUnsaved(true); return true; } @@ -463,30 +454,29 @@ private List> submitChunkLoadTasks(Region region, @Nullable private static ConfiguredFeature createTreeFeatureGenerator(TreeType type) { - switch (type) { - case TREE: return Features.OAK; - case BIG_TREE: return Features.FANCY_OAK; - case REDWOOD: return Features.SPRUCE; - case TALL_REDWOOD: return Features.MEGA_SPRUCE; - case MEGA_REDWOOD: return Features.MEGA_PINE; - case BIRCH: return Features.BIRCH; - case JUNGLE: return Features.MEGA_JUNGLE_TREE; - case SMALL_JUNGLE: return Features.JUNGLE_TREE; - case SHORT_JUNGLE: return Features.JUNGLE_TREE_NO_VINE; - case JUNGLE_BUSH: return Features.JUNGLE_BUSH; - case SWAMP: return Features.SWAMP_OAK; - case ACACIA: return Features.ACACIA; - case DARK_OAK: return Features.DARK_OAK; - case TALL_BIRCH: return Features.SUPER_BIRCH_BEES_0002; - case RED_MUSHROOM: return Features.HUGE_RED_MUSHROOM; - case BROWN_MUSHROOM: return Features.HUGE_BROWN_MUSHROOM; - case WARPED_FUNGUS: return Features.WARPED_FUNGI; - case CRIMSON_FUNGUS: return Features.CRIMSON_FUNGI; - case CHORUS_PLANT: return Features.CHORUS_PLANT; - case RANDOM: return createTreeFeatureGenerator(TreeType.values()[ThreadLocalRandom.current().nextInt(TreeType.values().length)]); - default: - return null; - } + return switch (type) { + case TREE -> TreeFeatures.OAK; + case BIG_TREE -> TreeFeatures.FANCY_OAK; + case REDWOOD -> TreeFeatures.SPRUCE; + case TALL_REDWOOD -> TreeFeatures.MEGA_SPRUCE; + case MEGA_REDWOOD -> TreeFeatures.MEGA_PINE; + case BIRCH -> TreeFeatures.BIRCH; + case JUNGLE -> TreeFeatures.MEGA_JUNGLE_TREE; + case SMALL_JUNGLE -> TreeFeatures.JUNGLE_TREE; + case SHORT_JUNGLE -> TreeFeatures.JUNGLE_TREE_NO_VINE; + case JUNGLE_BUSH -> TreeFeatures.JUNGLE_BUSH; + case SWAMP -> TreeFeatures.SWAMP_OAK; + case ACACIA -> TreeFeatures.ACACIA; + case DARK_OAK -> TreeFeatures.DARK_OAK; + case TALL_BIRCH -> TreeFeatures.SUPER_BIRCH_BEES_0002; + case RED_MUSHROOM -> TreeFeatures.HUGE_RED_MUSHROOM; + case BROWN_MUSHROOM -> TreeFeatures.HUGE_BROWN_MUSHROOM; + case WARPED_FUNGUS -> TreeFeatures.WARPED_FUNGUS; + case CRIMSON_FUNGUS -> TreeFeatures.CRIMSON_FUNGUS; + case CHORUS_PLANT -> EndFeatures.CHORUS_PLANT; + case RANDOM -> createTreeFeatureGenerator(TreeType.values()[ThreadLocalRandom.current().nextInt(TreeType.values().length)]); + default -> null; + }; } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index e6b09d361..1287e7f2b 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -59,6 +59,9 @@ import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickEmpty; +import net.minecraftforge.event.server.ServerAboutToStartEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -69,10 +72,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLPaths; -import net.minecraftforge.fmllegacy.network.FMLNetworkConstants; -import net.minecraftforge.fmlserverevents.FMLServerAboutToStartEvent; -import net.minecraftforge.fmlserverevents.FMLServerStartedEvent; -import net.minecraftforge.fmlserverevents.FMLServerStoppingEvent; +import net.minecraftforge.network.NetworkConstants; import net.minecraftforge.registries.ForgeRegistries; import org.apache.logging.log4j.Logger; import org.enginehub.piston.Command; @@ -129,7 +129,7 @@ public ForgeWorldEdit() { ModLoadingContext.get(), IExtensionPoint.DisplayTest.class, (Supplier) () -> new IExtensionPoint.DisplayTest( - () -> FMLNetworkConstants.IGNORESERVERONLY, + () -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true ) ); @@ -237,7 +237,7 @@ public void registerCommands(RegisterCommandsEvent event) { } @SubscribeEvent - public void serverAboutToStart(FMLServerAboutToStartEvent event) { + public void serverAboutToStart(ServerAboutToStartEvent event) { final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME); if (Files.exists(delChunks)) { ChunkDeleter.runFromFile(delChunks, true); @@ -245,14 +245,14 @@ public void serverAboutToStart(FMLServerAboutToStartEvent event) { } @SubscribeEvent - public void serverStopping(FMLServerStoppingEvent event) { + public void serverStopping(ServerStoppingEvent event) { WorldEdit worldEdit = WorldEdit.getInstance(); worldEdit.getSessionManager().unload(); WorldEdit.getInstance().getEventBus().post(new PlatformUnreadyEvent(platform)); } @SubscribeEvent - public void serverStarted(FMLServerStartedEvent event) { + public void serverStarted(ServerStartedEvent event) { setupRegistries(event.getServer()); config.load(); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java index c97c3a08e..da457b4b9 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java @@ -23,7 +23,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; +import net.minecraftforge.server.ServerLifecycleHooks; import java.util.Collections; import java.util.HashSet; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/InternalPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/InternalPacketHandler.java index 9e3e24ed8..9264f1978 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/InternalPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/InternalPacketHandler.java @@ -21,7 +21,7 @@ import com.sk89q.worldedit.forge.net.packet.LeftClickAirEventMessage; import com.sk89q.worldedit.forge.net.packet.LeftClickAirEventMessage.Handler; -import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; +import net.minecraftforge.network.simple.SimpleChannel; public final class InternalPacketHandler { private static final int PROTOCOL_VERSION = 1; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/PacketHandlerUtil.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/PacketHandlerUtil.java index eaa63dd14..a0a497bfc 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/PacketHandlerUtil.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/PacketHandlerUtil.java @@ -21,7 +21,7 @@ import com.sk89q.worldedit.forge.ForgeWorldEdit; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.fmllegacy.network.NetworkRegistry; +import net.minecraftforge.network.NetworkRegistry; import java.util.function.Predicate; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/WECUIPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/WECUIPacketHandler.java index 1c5b9985e..c64bf369b 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/WECUIPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/handler/WECUIPacketHandler.java @@ -23,8 +23,8 @@ import com.sk89q.worldedit.forge.ForgePlayer; import com.sk89q.worldedit.forge.ForgeWorldEdit; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.fmllegacy.network.NetworkEvent; -import net.minecraftforge.fmllegacy.network.event.EventNetworkChannel; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.event.EventNetworkChannel; import java.nio.charset.StandardCharsets; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/packet/LeftClickAirEventMessage.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/packet/LeftClickAirEventMessage.java index 2c4c2f40b..31ab4340a 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/packet/LeftClickAirEventMessage.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/net/packet/LeftClickAirEventMessage.java @@ -22,7 +22,7 @@ import com.sk89q.worldedit.forge.ForgeWorldEdit; import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickEmpty; -import net.minecraftforge.fmllegacy.network.NetworkEvent; +import net.minecraftforge.network.NetworkEvent; import java.util.Objects; import java.util.function.Supplier; From 7b4e2c28af49bb20673477e4df367f7a145c5fb4 Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 17:23:49 -0500 Subject: [PATCH 15/30] Bump forge version. Loads now, though Forge prod client/server still don't run. --- worldedit-forge/build.gradle.kts | 5 +++-- .../main/java/com/sk89q/worldedit/forge/ForgePlatform.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index 1e19a39b5..92a5b3eea 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -8,14 +8,14 @@ `java-library` } -applyPlatformAndCoreConfiguration(javaRelease = 16) +applyPlatformAndCoreConfiguration(javaRelease = 17) applyShadowConfiguration() val minecraftVersion = "1.18" val nextMajorMinecraftVersion: String = minecraftVersion.split('.').let { (useless, major) -> "$useless.${major.toInt() + 1}" } -val forgeVersion = "38.0.0" +val forgeVersion = "38.0.1" dependencies { "api"(project(":worldedit-core")) @@ -61,6 +61,7 @@ javaComponent.withVariantsFromConfiguration(configurations["runtimeElements"]) { skip() } + tasks.register("deobfJar") { from(sourceSets["main"].output) archiveClassifier.set("dev") diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index 113245746..876e5c36b 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -90,7 +90,7 @@ public Registries getRegistries() { @Override public int getDataVersion() { - return SharedConstants.getCurrentVersion().getWorldVersion(); + return SharedConstants.getCurrentVersion().getDataVersion().getVersion(); } @Override From 63d2ad4ec301f2ec3619012326466deb8e1acccc Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 20:11:35 -0500 Subject: [PATCH 16/30] Bump forge (again). --- buildSrc/build.gradle.kts | 2 +- worldedit-forge/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index ae7a4a392..528c1cecb 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -51,7 +51,7 @@ implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.0") implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.24.23") implementation("org.spongepowered:SpongeGradle:0.11.5") - implementation("net.minecraftforge.gradle:ForgeGradle:5.1.25") + implementation("net.minecraftforge.gradle:ForgeGradle:5.1.26") implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index 92a5b3eea..7c7fba110 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -15,7 +15,7 @@ val nextMajorMinecraftVersion: String = minecraftVersion.split('.').let { (useless, major) -> "$useless.${major.toInt() + 1}" } -val forgeVersion = "38.0.1" +val forgeVersion = "38.0.2" dependencies { "api"(project(":worldedit-core")) From f53282715ed972bd19292ae22fe9ae5db3114379 Mon Sep 17 00:00:00 2001 From: wizjany Date: Tue, 30 Nov 2021 22:19:14 -0500 Subject: [PATCH 17/30] Remove height from //expand vert. With new world height limits, this will cause more confusion than good. `//outset -v` or `//expand u,d` can replicate the previous behavior. --- .../worldedit/command/ExpandCommands.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java index bc54621c8..4686f6607 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ExpandCommands.java @@ -19,18 +19,15 @@ package com.sk89q.worldedit.command; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.command.argument.HeightConverter; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.MultiDirection; -import com.sk89q.worldedit.internal.annotation.VertHeight; import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -44,15 +41,12 @@ import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.inject.Key; -import org.enginehub.piston.part.CommandArgument; import org.enginehub.piston.part.SubCommandPart; import java.util.List; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; import static com.sk89q.worldedit.internal.command.CommandUtil.requireIV; -import static java.util.Objects.requireNonNull; -import static org.enginehub.piston.part.CommandParts.arg; /** * Extracted from {@link SelectionCommands} to allow importing of {@link Command}. @@ -93,32 +87,22 @@ public static void register(CommandRegistrationHandler registration, } private static Command createVertCommand(CommandManager commandManager) { - CommandArgument heightPart = arg( - TranslatableComponent.of("height"), - TextComponent.of("The height to expand both upwards and downwards") - ) - .defaultsTo(ImmutableList.of(HeightConverter.DEFAULT_VALUE)) - .build(); return commandManager.newCommand("vert") - .addPart(heightPart) .description(TranslatableComponent.of("worldedit.expand.description.vert")) .action(parameters -> { - int height = requireNonNull(parameters.valueOf(heightPart) - .asSingle(Key.of(int.class, VertHeight.class))); expandVert( requireIV(Key.of(LocalSession.class), "localSession", parameters), requireIV(Key.of(Actor.class), "actor", parameters), - requireIV(Key.of(World.class), "world", parameters), - height + requireIV(Key.of(World.class), "world", parameters) ); return 1; }) .build(); } - private static void expandVert(LocalSession session, Actor actor, World world, - int height) throws IncompleteRegionException { + private static void expandVert(LocalSession session, Actor actor, World world) throws IncompleteRegionException { Region region = session.getSelection(world); + int height = world.getMaxY() - world.getMinY(); try { long oldSize = region.getVolume(); region.expand( From a8656c5f24db0cfa20d4d4556790feb33271de66 Mon Sep 17 00:00:00 2001 From: wizjany Date: Thu, 2 Dec 2021 13:21:57 -0500 Subject: [PATCH 18/30] Bump some versions, fix forge run configs. --- buildSrc/build.gradle.kts | 2 +- worldedit-fabric/src/main/resources/pack.mcmeta | 2 +- worldedit-forge/build.gradle.kts | 13 +++++++++++-- worldedit-forge/src/main/resources/pack.mcmeta | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 528c1cecb..625b21f38 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -55,5 +55,5 @@ implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.0-SNAPSHOT") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.0") } diff --git a/worldedit-fabric/src/main/resources/pack.mcmeta b/worldedit-fabric/src/main/resources/pack.mcmeta index b48da3b7d..0a39f614a 100644 --- a/worldedit-fabric/src/main/resources/pack.mcmeta +++ b/worldedit-fabric/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { "description": "WorldEdit Resources", - "pack_format": 4 + "pack_format": 8 } } \ No newline at end of file diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index 7c7fba110..d7c9eebdc 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -15,10 +15,14 @@ val nextMajorMinecraftVersion: String = minecraftVersion.split('.').let { (useless, major) -> "$useless.${major.toInt() + 1}" } -val forgeVersion = "38.0.2" +val forgeVersion = "38.0.10" + +val apiClasspath = configurations.create("apiClasspath") +apiClasspath.isCanBeResolved = true +configurations.api.get().extendsFrom(apiClasspath) dependencies { - "api"(project(":worldedit-core")) + "apiClasspath"(project(":worldedit-core")) "implementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { because("Mojang provides Log4J at 2.14.1") }) @@ -45,6 +49,11 @@ } create("client", runConfig) create("server", runConfig) + all { + lazyToken("minecraft_classpath") { + apiClasspath.copyRecursive().resolve().joinToString(File.pathSeparator) { it.absolutePath } + } + } } } diff --git a/worldedit-forge/src/main/resources/pack.mcmeta b/worldedit-forge/src/main/resources/pack.mcmeta index b48da3b7d..0a39f614a 100644 --- a/worldedit-forge/src/main/resources/pack.mcmeta +++ b/worldedit-forge/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { "description": "WorldEdit Resources", - "pack_format": 4 + "pack_format": 8 } } \ No newline at end of file From 46de95ff3c0cc9cb0893de41c8a349000cd2089c Mon Sep 17 00:00:00 2001 From: wizjany Date: Thu, 2 Dec 2021 14:43:49 -0500 Subject: [PATCH 19/30] Clean up forge gradle script, apply the chorus plant fix to forge/fabric world. --- .../sk89q/worldedit/fabric/FabricWorld.java | 3 +++ worldedit-forge/build.gradle.kts | 22 ++++++++----------- .../com/sk89q/worldedit/forge/ForgeWorld.java | 3 +++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index 987389b1b..f6214d571 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -487,6 +487,9 @@ public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 ConfiguredFeature generator = createTreeFeatureGenerator(type); ServerLevel world = (ServerLevel) getWorld(); ServerChunkCache chunkManager = world.getChunkSource(); + if (type == TreeType.CHORUS_PLANT) { + position = position.add(0, 1, 0); + } return generator != null && generator.place( world, chunkManager.getGenerator(), random, FabricAdapter.toBlockPos(position) diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index d7c9eebdc..b429b2140 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -17,12 +17,13 @@ } val forgeVersion = "38.0.10" -val apiClasspath = configurations.create("apiClasspath") -apiClasspath.isCanBeResolved = true -configurations.api.get().extendsFrom(apiClasspath) +val apiClasspath = configurations.create("apiClasspath") { + isCanBeResolved = true + extendsFrom(configurations.api.get()) +} dependencies { - "apiClasspath"(project(":worldedit-core")) + "api"(project(":worldedit-core")) "implementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { because("Mojang provides Log4J at 2.14.1") }) @@ -31,10 +32,7 @@ } configure { - mappings(mapOf( - "channel" to "official", - "version" to minecraftVersion - )) + mappings("official", minecraftVersion) accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg")) @@ -46,14 +44,12 @@ )) workingDirectory = project.file("run").canonicalPath source(sourceSets["main"]) + lazyToken("minecraft_classpath") { + apiClasspath.resolve().joinToString(File.pathSeparator) { it.absolutePath } + } } create("client", runConfig) create("server", runConfig) - all { - lazyToken("minecraft_classpath") { - apiClasspath.copyRecursive().resolve().joinToString(File.pathSeparator) { it.absolutePath } - } - } } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 573a4146d..4b14d6702 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -484,6 +484,9 @@ public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 ConfiguredFeature generator = createTreeFeatureGenerator(type); ServerLevel world = getWorld(); ServerChunkCache chunkManager = world.getChunkSource(); + if (type == TreeType.CHORUS_PLANT) { + position = position.add(0, 1, 0); + } return generator != null && generator.place( world, chunkManager.getGenerator(), random, ForgeAdapter.toBlockPos(position) ); From bfef9962f46f183708f8f74d20202207eca24707 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sat, 4 Dec 2021 13:27:38 -0500 Subject: [PATCH 20/30] Fix BlockEntity saving on Forge. --- .../com/sk89q/worldedit/forge/internal/TileEntityUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java index ddaa59d7f..d49574f67 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java @@ -50,6 +50,6 @@ static boolean setTileEntity(Level world, BlockPos position, CompoundTag tag) { } public static CompoundTag copyNbtData(BlockEntity tile) { - return tile.save(new CompoundTag()); + return tile.saveWithId(); } } From 22816cffe94f3166675edefba885f59819e06d56 Mon Sep 17 00:00:00 2001 From: wizjany Date: Fri, 10 Dec 2021 08:58:42 -0500 Subject: [PATCH 21/30] Version bumps for bukkit/fabric 1.18.1 --- .../bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java | 4 ++-- worldedit-fabric/build.gradle.kts | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java index 713c7d1c0..2fe91b219 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.18/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_18_R1/PaperweightAdapter.java @@ -186,8 +186,8 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { CraftServer.class.cast(Bukkit.getServer()); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2860) { - throw new UnsupportedClassVersionError("Not 1.18!"); + if (dataVersion != 2860 && dataVersion != 2865) { + throw new UnsupportedClassVersionError("Not 1.18(.1)!"); } serverWorldsField = CraftServer.class.getDeclaredField("worlds"); diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index ce0be43bf..8c998bae5 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -21,9 +21,8 @@ apply(plugin = "fabric-loom") apply(plugin = "java-library") -val minecraftVersion = "1.18" -val yarnMappings = "1.18+build.1:v2" -val loaderVersion = "0.12.6" +val minecraftVersion = "1.18.1" +val loaderVersion = "0.12.9" val fabricApiConfiguration: Configuration = configurations.create("fabricApi") @@ -49,7 +48,7 @@ "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") // [1] declare fabric-api dependency... - "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.43.1+1.18") + "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.44.0+1.18") // [2] Load the API dependencies from the fabric mod json... @Suppress("UNCHECKED_CAST") From 1246d61030ec3e6abc88f9d25270b975e80b3eb5 Mon Sep 17 00:00:00 2001 From: Madeline Miller Date: Sat, 11 Dec 2021 14:38:26 +1000 Subject: [PATCH 22/30] Release 7.2.8 --- CHANGELOG.txt | 6 ++++++ gradle.properties | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f93ba6f3f..26249a578 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,9 @@ +7.2.8 +- Update to 1.18.1 +- Fixed issues with certain imports in craftscripts +- Fixed brush tracing counting the world limit as a placement location +- Removed the height flag from //expand vert + 7.2.7 - [Bukkit] Update 1.17.1 adapters for recent Spigot worldgen change - [Bukkit] Minor improvements to world access performance diff --git a/gradle.properties b/gradle.properties index 9ac9b3f62..b6b765d73 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=com.sk89q.worldedit -version=7.2.8-SNAPSHOT +version=7.2.8 org.gradle.jvmargs=-Xmx1512M org.gradle.parallel=true From 4f34cf9fcbe3d1057ab24c5367f7524a717027dc Mon Sep 17 00:00:00 2001 From: Madeline Miller Date: Sat, 11 Dec 2021 14:39:43 +1000 Subject: [PATCH 23/30] Back to SNAPSHOT for continued development --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index b6b765d73..1005ed9d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=com.sk89q.worldedit -version=7.2.8 +version=7.2.9-SNAPSHOT org.gradle.jvmargs=-Xmx1512M org.gradle.parallel=true From 885c326cee3fec53c2241bc2024358ec91eda1ac Mon Sep 17 00:00:00 2001 From: wizjany Date: Sun, 12 Dec 2021 17:27:22 -0500 Subject: [PATCH 24/30] Bump paperweight, dev bundle. --- buildSrc/build.gradle.kts | 2 +- worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 625b21f38..2577df37e 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -55,5 +55,5 @@ implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.0") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.2") } diff --git a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts index f75b37a9b..2c478b056 100644 --- a/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.18/build.gradle.kts @@ -1,5 +1,6 @@ applyPaperweightAdapterConfiguration() dependencies { - paperDevBundle("1.18-R0.1-20211130.173143-6") + // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ + paperDevBundle("1.18.1-R0.1-20211212.093039-5") } From 2c0b47d7db41cf32019a27dfc439898fe179d2e8 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sun, 12 Dec 2021 18:11:24 -0500 Subject: [PATCH 25/30] Bump forge version as well. --- worldedit-forge/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index b429b2140..acefda806 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -11,11 +11,11 @@ applyPlatformAndCoreConfiguration(javaRelease = 17) applyShadowConfiguration() -val minecraftVersion = "1.18" +val minecraftVersion = "1.18.1" val nextMajorMinecraftVersion: String = minecraftVersion.split('.').let { (useless, major) -> "$useless.${major.toInt() + 1}" } -val forgeVersion = "38.0.10" +val forgeVersion = "39.0.0" val apiClasspath = configurations.create("apiClasspath") { isCanBeResolved = true From 20c42b51c8bfbcecb83e8c3fade6274a090f3763 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sun, 12 Dec 2021 18:49:32 -0500 Subject: [PATCH 26/30] Extract log4j version to Versions.kt. Also bump to match underlying platform versions to resolve runtime version mismatches. --- buildSrc/src/main/kotlin/Versions.kt | 1 + worldedit-bukkit/build.gradle.kts | 2 +- worldedit-cli/build.gradle.kts | 2 +- worldedit-core/build.gradle.kts | 6 +++--- worldedit-fabric/build.gradle.kts | 4 ++-- worldedit-forge/build.gradle.kts | 4 ++-- worldedit-sponge/build.gradle.kts | 4 ++-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index c704bfe73..b03007fcc 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -10,6 +10,7 @@ const val FAST_UTIL = "8.5.6" const val GUAVA = "31.0.1-jre" const val GSON = "2.8.8" + const val LOG4J = "2.15.0" } // Properties that need a project reference to resolve: diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 22264c177..5b37794ca 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -40,7 +40,7 @@ exclude("junit", "junit") } - "localImplementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { + "localImplementation"(platform("org.apache.logging.log4j:log4j-bom:${Versions.LOG4J}") { because("Spigot provides Log4J (sort of, not in API, implicitly part of server)") }) "localImplementation"("org.apache.logging.log4j:log4j-api") diff --git a/worldedit-cli/build.gradle.kts b/worldedit-cli/build.gradle.kts index bb0a65208..718bc608a 100644 --- a/worldedit-cli/build.gradle.kts +++ b/worldedit-cli/build.gradle.kts @@ -19,7 +19,7 @@ "annotationProcessor"(project(":worldedit-libs:core:ap")) "annotationProcessor"("com.google.guava:guava:${Versions.GUAVA}") "api"(project(":worldedit-core")) - "implementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { + "implementation"(platform("org.apache.logging.log4j:log4j-bom:${Versions.LOG4J}") { because("We control Log4J on this platform") }) "implementation"("org.apache.logging.log4j:log4j-api") diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 8cc793221..0e7c38abf 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -42,8 +42,8 @@ "implementation"("com.google.code.findbugs:jsr305:1.3.9") "implementation"("com.google.code.gson:gson") - "implementation"("org.apache.logging.log4j:log4j-api:2.14.1") { - because("Mojang provides Log4J 2.14.1") + "implementation"("org.apache.logging.log4j:log4j-api:${Versions.LOG4J}") { + because("Mojang provides Log4J") } "implementation"("it.unimi.dsi:fastutil") @@ -61,7 +61,7 @@ "languageFiles"("${project.group}:worldedit-lang:7.2.6:355@zip") - "testRuntimeOnly"("org.apache.logging.log4j:log4j-core:2.14.1") + "testRuntimeOnly"("org.apache.logging.log4j:log4j-core:${Versions.LOG4J}") } tasks.named("test") { diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 8c998bae5..f7b152588 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -39,8 +39,8 @@ dependencies { "api"(project(":worldedit-core")) - "implementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { - because("Mojang provides Log4J at 2.14.1") + "implementation"(platform("org.apache.logging.log4j:log4j-bom:${Versions.LOG4J}") { + because("Mojang provides Log4J") }) "minecraft"("com.mojang:minecraft:$minecraftVersion") diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index acefda806..c9fb12b1c 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -24,8 +24,8 @@ dependencies { "api"(project(":worldedit-core")) - "implementation"(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { - because("Mojang provides Log4J at 2.14.1") + "implementation"(platform("org.apache.logging.log4j:log4j-bom:${Versions.LOG4J}") { + because("Mojang provides Log4J") }) "minecraft"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index aa2cb0da8..affa68b86 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -23,8 +23,8 @@ api("org.spongepowered:spongeapi:7.1.0") { exclude(group = "org.slf4j", module = "slf4j-api") } - implementation(platform("org.apache.logging.log4j:log4j-bom:2.14.1") { - because("Sponge 8 (will?) provides Log4J at 2.14.1") + implementation(platform("org.apache.logging.log4j:log4j-bom:${Versions.LOG4J}") { + because("Sponge 8 (will?) provides Log4J") }) api("org.apache.logging.log4j:log4j-api") api("org.bstats:bstats-sponge:1.7") From 12e1c242cea874387d003a17df1bcdc53689e32b Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Mon, 13 Dec 2021 22:09:32 -0800 Subject: [PATCH 27/30] Update flows from master --- .github/workflows/codeql-analysis.yml | 63 +++++++++++++++++++++++++++ .github/workflows/gradle.yml | 8 ++-- 2 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..da9cf78a9 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,63 @@ +name: "CodeQL" + +on: + push: + branches: [ master, version/**/* ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master, version/**/* ] + schedule: + - cron: '45 0 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: 17 + cache: 'gradle' + distribution: 'temurin' + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 60729d2d5..51c37f62c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -12,13 +12,15 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 16 + - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 16 + java-version: 17 + cache: 'gradle' + distribution: 'temurin' - name: Build with Gradle run: ./gradlew build -s - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v2.2.4 name: Archive Reports if: always() with: From 100b87ea9820bf35453fcc3beff4c054cd67f8db Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Mon, 13 Dec 2021 22:15:58 -0800 Subject: [PATCH 28/30] Update gradle flow properly --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 51c37f62c..a407c4137 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up JDK - uses: actions/setup-java@v1 + uses: actions/setup-java@v2 with: java-version: 17 cache: 'gradle' From 9843a4feb34810e07978bf083b42df067955df4b Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Tue, 14 Dec 2021 18:32:39 +0100 Subject: [PATCH 29/30] Fix snapshots in 1.18 (#1959) * Fix snapshots in 1.18 * use Int2ObjectOpenHashMap * Fix loading zipped snapshots that contain an entities folder Co-authored-by: Octavia Togami --- .../sk89q/worldedit/internal/Constants.java | 4 + .../worldedit/world/chunk/AnvilChunk16.java | 2 +- .../worldedit/world/chunk/AnvilChunk18.java | 222 ++++++++++++++++++ .../world/storage/ChunkStoreHelper.java | 42 +++- .../storage/TrueZipMcRegionChunkStore.java | 2 +- .../storage/ZippedMcRegionChunkStore.java | 2 +- 6 files changed, 258 insertions(+), 16 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java 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 713458e65..842e5b1bd 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 @@ -72,4 +72,8 @@ private Constants() { */ public static final int DATA_VERSION_MC_1_17 = 2724; + /** + * The DataVersion for Minecraft 1.18 + */ + public static final int DATA_VERSION_MC_1_18 = 2860; } 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 bd9d5e08a..e7bfbd205 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 @@ -25,7 +25,7 @@ import com.sk89q.worldedit.world.storage.InvalidFormatException; /** - * The chunk format for Minecraft 1.16 and newer + * The chunk format for Minecraft 1.16 and 1.17 */ public class AnvilChunk16 extends AnvilChunk13 { 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 new file mode 100644 index 000000000..e71c730ff --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java @@ -0,0 +1,222 @@ +/* + * 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.chunk; + +import com.sk89q.jnbt.CompoundTag; +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.world.DataException; +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.storage.InvalidFormatException; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * The chunk format for Minecraft 1.18 and newer + */ +public class AnvilChunk18 implements Chunk { + + private final CompoundTag rootTag; + private final Int2ObjectOpenHashMap blocks; + 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 + */ + public AnvilChunk18(CompoundTag tag) throws DataException { + rootTag = tag; + + 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 (Tag rawSectionTag : sections) { + if (!(rawSectionTag instanceof CompoundTag)) { + continue; + } + + 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(); + + 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 + 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++) { + 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(); + if (paletteEntry.containsKey("Properties")) { + CompoundTag properties = NBTUtils.getChildTag(paletteEntry.getValue(), "Properties", CompoundTag.class); + for (Property property : blockState.getStates().keySet()) { + 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); + } + } + } + } + palette[paletteEntryId] = blockState; + } + if (paletteSize == 1) { + // the same block everywhere + blocks.put(y, palette); + continue; + } + + // parse block states + long[] blockStatesSerialized = NBTUtils.getChildTag(blockStatesTag.getValue(), "data", LongArrayTag.class).getValue(); + + BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; + blocks.put(y, chunkSectionBlocks); + + readBlockStates(palette, blockStatesSerialized, chunkSectionBlocks); + } + } + } + + protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws InvalidFormatException { + PackedIntArrayReader reader = new PackedIntArrayReader(blockStatesSerialized); + for (int blockPos = 0; blockPos < chunkSectionBlocks.length; blockPos++) { + int index = reader.get(blockPos); + if (index >= palette.length) { + throw new InvalidFormatException("Invalid block state table entry: " + index); + } + chunkSectionBlocks[blockPos] = palette[index]; + } + } + + private BlockState getBlockStateWith(BlockState source, Property property, String value) { + return source.with(property, property.getValueFor(value)); + } + + /** + * Used to load the tile entities. + */ + private void populateTileEntities() throws DataException { + tileEntities = new HashMap<>(); + if (!rootTag.getValue().containsKey("block_entities")) { + return; + } + 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"); + } + + 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, values); + } + } + + /** + * Get the map of tags keyed to strings for a block's tile entity data. May + * return null if there is no tile entity data. Not public yet because + * what this function returns isn't ideal for usage. + * + * @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 CompoundTag getBlockTileEntity(BlockVector3 position) throws DataException { + if (tileEntities == null) { + populateTileEntities(); + } + + 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() - rootX * 16; + int y = position.getY(); + int z = position.getZ() - rootZ * 16; + + int section = y >> 4; + int yIndex = y & 0x0F; + + BlockState[] sectionBlocks = blocks.get(section); + if (sectionBlocks == null) { + return BlockTypes.AIR.getDefaultState().toBaseBlock(); + } + BlockState state = sectionBlocks[sectionBlocks.length == 1 ? 0 : ((yIndex << 8) | (z << 4) | x)]; + + CompoundTag tileEntity = getBlockTileEntity(position); + + if (tileEntity != null) { + return state.toBaseBlock(tileEntity); + } + + return state.toBaseBlock(); + } + +} 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 70f189f6f..833c1d402 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 @@ -31,6 +31,7 @@ import com.sk89q.worldedit.world.chunk.AnvilChunk; import com.sk89q.worldedit.world.chunk.AnvilChunk13; import com.sk89q.worldedit.world.chunk.AnvilChunk16; +import com.sk89q.worldedit.world.chunk.AnvilChunk18; import com.sk89q.worldedit.world.chunk.Chunk; import com.sk89q.worldedit.world.chunk.OldChunk; @@ -68,6 +69,25 @@ public static CompoundTag readCompoundTag(ChunkDataInputSupplier input) throws D * @throws DataException if the rootTag is not valid chunk data */ public static Chunk getChunk(CompoundTag rootTag) throws DataException { + int dataVersion = rootTag.getInt("DataVersion"); + if (dataVersion == 0) { + dataVersion = -1; + } + + final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + final int currentDataVersion = platform.getDataVersion(); + 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) { + rootTag = dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion); + dataVersion = currentDataVersion; + } + } + + if (dataVersion >= Constants.DATA_VERSION_MC_1_18) { + return new AnvilChunk18(rootTag); + } + Map children = rootTag.getValue(); CompoundTag tag = null; @@ -87,19 +107,6 @@ public static Chunk getChunk(CompoundTag rootTag) throws DataException { throw new ChunkStoreException("Missing root 'Level' tag"); } - int dataVersion = rootTag.getInt("DataVersion"); - if (dataVersion == 0) { - dataVersion = -1; - } - final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); - final int currentDataVersion = platform.getDataVersion(); - if (tag.getValue().containsKey("Sections") && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks - final DataFixer dataFixer = platform.getDataFixer(); - if (dataFixer != null) { - tag = (CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level"); - dataVersion = currentDataVersion; - } - } if (dataVersion >= Constants.DATA_VERSION_MC_1_16) { return new AnvilChunk16(tag); } @@ -115,6 +122,15 @@ public static Chunk getChunk(CompoundTag rootTag) throws DataException { return new OldChunk(tag); } + private static boolean hasLevelSections(CompoundTag rootTag) { + Map children = rootTag.getValue(); + Tag levelTag = children.get("Level"); + if (levelTag instanceof CompoundTag) { + return ((CompoundTag) levelTag).getValue().containsKey("Sections"); + } + return false; + } + private ChunkStoreHelper() { } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/TrueZipMcRegionChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/TrueZipMcRegionChunkStore.java index 679d7257c..37e62e0fc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/TrueZipMcRegionChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/TrueZipMcRegionChunkStore.java @@ -106,7 +106,7 @@ protected InputStream getInputStream(String name, String worldName) throws IOExc endIndex = entryName.lastIndexOf('\\'); } folder = entryName.substring(0, endIndex); - if (folder.endsWith("poi")) { + if (folder.endsWith("poi") || folder.endsWith("entities")) { continue; } name = folder + "/" + name; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ZippedMcRegionChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ZippedMcRegionChunkStore.java index 030004ee3..a4ea0937c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ZippedMcRegionChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ZippedMcRegionChunkStore.java @@ -93,7 +93,7 @@ protected InputStream getInputStream(String name, String worldName) throws IOExc endIndex = entryName.lastIndexOf('\\'); } folder = entryName.substring(0, endIndex); - if (folder.endsWith("poi")) { + if (folder.endsWith("poi") || folder.endsWith("entities")) { continue; } name = folder + "/" + name; From 92dfe5e44ef7549bc3670ed726e0be924dcf13e3 Mon Sep 17 00:00:00 2001 From: Madeline Miller Date: Tue, 21 Dec 2021 19:49:48 +1000 Subject: [PATCH 30/30] Bump Paperweight to allow 1.17 adapters from source --- buildSrc/build.gradle.kts | 2 +- .../adapters/adapter-1.17.1/build.gradle.kts | 18 +++--------------- .../resources/worldedit-adapter-1.17.1.jar | Bin 124505 -> 0 bytes .../adapters/adapter-1.18/build.gradle.kts | 2 +- 4 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 2577df37e..b6be0fdfd 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -55,5 +55,5 @@ implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") implementation("org.enginehub.gradle:gradle-codecov-plugin:0.1.0") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.2") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.3") } diff --git a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts index 82717cc98..1b4444d6e 100644 --- a/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1.17.1/build.gradle.kts @@ -1,17 +1,5 @@ -// TODO await https://github.com/PaperMC/paperweight/issues/116 -//applyPaperweightAdapterConfiguration() -// -//dependencies { -// paperDevBundle("1.17.1-R0.1-20211120.192557-194") -//} +applyPaperweightAdapterConfiguration() -// Until the above issue is resolved, we are bundling old versions using their last assembled JAR. -// Technically this means we cannot really update them, but that is is the price we pay for supporting older versions. - -plugins { - base -} - -artifacts { - add("default", file("./src/main/resources/worldedit-adapter-1.17.1.jar")) +dependencies { + paperDevBundle("1.17.1-R0.1-20211219.175449-201") } diff --git a/worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar b/worldedit-bukkit/adapters/adapter-1.17.1/src/main/resources/worldedit-adapter-1.17.1.jar deleted file mode 100644 index d370dc4e95700f713b3bde2ac2ec12f33feb09e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124505 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