diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bc78076bdc..1de1aa8dfa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -27,10 +27,9 @@ body: description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. multiple: false options: - - '1.20.4' + - '1.20.5/6' - '1.20' - '1.19.4' - - '1.18.2' validations: required: true diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index fbb90ab03b..e6ad24a7fd 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -17,7 +17,7 @@ jobs: with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Build on ${{ matrix.os }} run: ./gradlew build -s - name: Archive artifacts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6072de2f0..5b44758dd6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Clean Build run: ./gradlew clean build --no-daemon - name: Determine release status diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b7e9c61ed0..0cd6f44439 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -25,7 +25,7 @@ jobs: with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: diff --git a/.github/workflows/label-merge-conflicts.yaml b/.github/workflows/label-merge-conflicts.yaml index fa6f3d72dc..551b394172 100644 --- a/.github/workflows/label-merge-conflicts.yaml +++ b/.github/workflows/label-merge-conflicts.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Label conflicting PRs - uses: eps1lon/actions-label-merge-conflict@v3.0.0 + uses: eps1lon/actions-label-merge-conflict@v3.0.1 with: dirtyLabel: "unresolved-merge-conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/upload-release-assets.yml b/.github/workflows/upload-release-assets.yml index bff53a6b23..22d6c60830 100644 --- a/.github/workflows/upload-release-assets.yml +++ b/.github/workflows/upload-release-assets.yml @@ -15,7 +15,7 @@ jobs: with: distribution: temurin cache: gradle - java-version: 17 + java-version: 21 - name: Clean Build run: ./gradlew clean build --no-daemon - name: Upload Release Assets diff --git a/COMPILING.adoc b/COMPILING.adoc index 87b21b685e..bdd30ba621 100644 --- a/COMPILING.adoc +++ b/COMPILING.adoc @@ -3,12 +3,12 @@ = Compiling -You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed, +You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 21 installed. Gradle will download JDK 21 specifically if needed, but it needs some version of Java to bootstrap from. -Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 17. +Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 21. -You can get the JDK 17 link:https://adoptium.net/[here] from Adoptium. +You can get the JDK 21 link:https://adoptium.net/[here] from Adoptium. The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules: diff --git a/Jenkinsfile b/Jenkinsfile index 61000e9fb8..94db4eda21 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { stage('Build') { steps { withEnv([ - "PATH+JAVA=${tool 'Temurin-17.0.7_7'}/bin" + "PATH+JAVA=${tool 'Temurin-21.0.3_9'}/bin" ]) { sh './gradlew clean build' } diff --git a/build.gradle.kts b/build.gradle.kts index 8086d4bdad..8fdea32009 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer plugins { id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("xyz.jpenilla.run-paper") version "2.2.3" + id("xyz.jpenilla.run-paper") version "2.3.0" } if (!File("$rootDir/.git").exists()) { @@ -34,7 +34,7 @@ logger.lifecycle(""" ******************************************* """) -var rootVersion by extra("2.9.3") +var rootVersion by extra("2.10.1") var snapshot by extra("SNAPSHOT") var revision: String by extra("") var buildNumber by extra("") @@ -83,7 +83,7 @@ allprojects { } applyCommonConfiguration() -val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") +val supportedVersions = listOf("1.19.4", "1.20", "1.20.4", "1.20.5", "1.20.6") tasks { supportedVersions.forEach { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 651397b27e..fe8a81bc3c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -28,11 +28,23 @@ dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") implementation("com.github.johnrengelman:shadow:8.1.1") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.15") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.1") + constraints { + val asmVersion = "[9.7,)" + implementation("org.ow2.asm:asm:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.ow2.asm:asm-commons:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.vafer:jdependency:[2.10,)") { + because("Need Java 21 support in shadow") + } + } } kotlin { jvmToolchain { - (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17)) + (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(21)) } } diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt index e84de576e2..3d98007494 100644 --- a/buildSrc/src/main/kotlin/CommonConfig.kt +++ b/buildSrc/src/main/kotlin/CommonConfig.kt @@ -37,7 +37,7 @@ fun Project.applyCommonConfiguration() { plugins.withId("java") { the().toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(21)) } } diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 8a111a2e76..fec02d1a04 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -21,7 +21,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean .matching { it.name == "compileJava" || it.name == "compileTestJava" } .configureEach { val disabledLint = listOf( - "processing", "path", "fallthrough", "serial" + "processing", "path", "fallthrough", "serial", "overloads", "this-escape", ) options.release.set(17) options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) @@ -31,7 +31,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean } configurations.all { - attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } tasks.withType().configureEach { @@ -61,7 +61,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean "https://jd.advntr.dev/api/latest/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://www.antlr.org/api/Java/", - "https://jd.papermc.io/paper/1.20/", + "https://jd.papermc.io/paper/1.20.6/", "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" ) docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 5d6e7892b3..2c957880a8 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -122,7 +122,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } outgoing.artifact(tasks.named("jar")) } @@ -137,7 +137,7 @@ fun Project.applyLibrariesConfiguration() { attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) } outgoing.artifact(tasks.named("jar")) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d56b9c9ea..639b7b0103 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # Minecraft expectations -paper = "1.20.4-R0.1-SNAPSHOT" +paper = "1.20.6-R0.1-SNAPSHOT" fastutil = "8.5.9" guava = "31.1-jre" log4j = "2.19.0" @@ -9,25 +9,25 @@ snakeyaml = "2.0" # Plugins dummypermscompat = "1.10" -worldguard-bukkit = "7.0.9" +worldguard-bukkit = "7.0.10" mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.100.2.3" +towny = "0.100.2.9" plotsquared = "7.3.8" # Third party bstats = "3.0.2" sparsebitset = "1.3" parallelgzip = "1.0.5" -adventure = "4.16.0" +adventure = "4.17.0" adventure-bukkit = "4.3.2" -checkerqual = "3.42.0" +checkerqual = "3.43.0" truezip = "6.8.4" auto-value = "1.10.4" findbugs = "3.0.2" -rhino-runtime = "1.7.14" +rhino-runtime = "1.7.15" zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs antlr4 = "4.13.1" json-simple = "1.1.1" @@ -35,7 +35,7 @@ jlibnoise = "1.0.0" jchronic = "0.2.4a" lz4-java = "1.8.0" lz4-stream = "1.0.0" -commons-cli = "1.6.0" +commons-cli = "1.7.0" paperlib = "1.0.8" paster = "1.1.6" vault = "1.7.1" @@ -46,7 +46,7 @@ text = "3.0.4" piston = "0.5.10" # Tests -mockito = "5.11.0" +mockito = "5.12.0" # Gradle plugins pluginyml = "0.6.0" diff --git a/settings.gradle.kts b/settings.gradle.kts index 6dd6048b6e..c2bbe1807f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit" include("worldedit-libs") -listOf("1_18_2", "1_19_4", "1_20", "1_20_2", "1_20_4").forEach { +listOf("1_19_4", "1_20", "1_20_2", "1_20_4", "1_20_5").forEach { include("worldedit-bukkit:adapters:adapter-$it") } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts index d626798e02..821b6c52dc 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT - the().paperDevBundle("1.20.4-R0.1-20240420.200855-173") + the().paperDevBundle("1.20.4-R0.1-20240424.165410-174") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index 147ec5be76..23de00adea 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -58,7 +58,6 @@ import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R3.CraftChunk; -import sun.misc.Unsafe; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts similarity index 78% rename from worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts rename to worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts index 3713af2077..a0ee57dc22 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts @@ -11,7 +11,7 @@ repositories { } dependencies { - // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.18.2-R0.1-SNAPSHOT - the().paperDevBundle("1.18.2-R0.1-20220920.010157-167") + // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ + the().paperDevBundle("1.20.6-R0.1-20240520.005421-60") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java similarity index 77% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java index 1edc3be1d9..e629c46118 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java @@ -17,24 +17,23 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; -import com.google.common.collect.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.Lifecycle; +import com.sk89q.jnbt.NBTConstants; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightPlatformAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.Extent; @@ -81,14 +80,20 @@ import com.sk89q.worldedit.world.item.ItemType; import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; @@ -112,10 +117,10 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.phys.BlockHitResult; @@ -124,13 +129,13 @@ import org.bukkit.Location; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_18_R2.util.CraftMagicNumbers; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.generator.ChunkGenerator; @@ -155,7 +160,6 @@ import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -166,33 +170,28 @@ public final class PaperweightAdapter implements BukkitImplAdapter { - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, - SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE - ); + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + private final Field serverWorldsField; private final Method getChunkFutureMethod; private final Field chunkProviderExecutorField; - private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); + private final Watchdog watchdog; // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ - private final Watchdog watchdog; - private final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { // A simple test CraftServer.class.cast(Bukkit.getServer()); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); - if (dataVersion != 2975) { - throw new UnsupportedClassVersionError("Not 1.18.2!"); + if (dataVersion != 3837 && dataVersion != 3839) { + throw new UnsupportedClassVersionError("Not 1.20.(5/6)!"); } serverWorldsField = CraftServer.class.getDeclaredField("worlds"); @@ -209,7 +208,7 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { ); chunkProviderExecutorField.setAccessible(true); - new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); + new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized(); Watchdog watchdog; try { @@ -231,6 +230,11 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { } } + @Override + public DataFixer getDataFixer() { + return PaperweightDataConverters.INSTANCE; + } + /** * Read the given NBT data into the given tile entity. * @@ -238,7 +242,7 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { * @param tag the tag */ static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) { - tileEntity.load(tag); + tileEntity.loadWithComponents(tag, MinecraftServer.getServer().registryAccess()); tileEntity.setChanged(); } @@ -271,9 +275,7 @@ private static Entity createEntityFromId(String id, net.minecraft.world.level.Le * @param tag the tag */ private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { - //FAWE start - avoid villager async catcher - PaperweightPlatformAdapter.readEntityIntoTag(entity, tag); - //FAWE end + entity.load(tag); } /** @@ -287,34 +289,14 @@ private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundT } 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())); + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse( + blockType.getId())); } - 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; - } - } - - @Override - public DataFixer getDataFixer() { - return PaperweightDataConverters.INSTANCE; + private static Item getItemFromType(ItemType itemType) { + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse( + itemType.getId())); } @Override @@ -334,6 +316,25 @@ public OptionalInt getInternalBlockStateId(BlockState state) { return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); } + public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + int internalId = Block.getId(blockState); + BlockState state = BlockStateIdAccess.getBlockStateById(internalId); + if (state == null) { + state = BukkitAdapter.adapt(CraftBlockData.createData(blockState)); + } + + return state; + } + + public BiomeType adapt(Biome biome) { + var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey( + biome); + if (mcBiome == null) { + return null; + } + return BiomeType.REGISTRY.get(mcBiome.toString()); + } + @Override public BlockState getBlock(Location location) { checkNotNull(location); @@ -373,21 +374,37 @@ public BaseBlock getFullBlock(Location location) { // Read the NBT data BlockEntity te = chunk.getBlockEntity(blockPos); if (te != null) { - net.minecraft.nbt.CompoundTag tag = te.saveWithId(); - //FAWE start - BinaryTag + net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess()); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); - //FAWE end } return state.toBaseBlock(); } + private static final HashMap> biomeTypeToNMSCache = new HashMap<>(); + private static final HashMap, BiomeType> biomeTypeFromNMSCache = new HashMap<>(); + @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { - return new PaperweightWorldNativeAccess( - this, - new WeakReference<>(((CraftWorld) world).getHandle()) - ); + 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"}) @@ -429,16 +446,19 @@ public BaseEntity getEntity(org.bukkit.entity.Entity entity) { CraftEntity craftEntity = ((CraftEntity) entity); Entity mcEntity = craftEntity.getHandle(); + // Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity + if (mcEntity.isPassenger()) { + return null; + } + String id = getEntityId(mcEntity); net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); readEntityIntoTag(mcEntity, tag); - //FAWE start - CompoundBinaryTag return new BaseEntity( com.sk89q.worldedit.world.entity.EntityTypes.get(id), LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)) ); - //FAWE end } @Nullable @@ -471,6 +491,22 @@ public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state } } + // This removes all unwanted tags from the main entity and all its passengers + private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) { + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + + // Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive + if (tag.contains("Passengers", NBTConstants.TYPE_LIST)) { + net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", NBTConstants.TYPE_COMPOUND); + + for (int i = 0; i < nbttaglist.size(); ++i) { + removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i)); + } + } + } + @Override public Component getRichBlockName(BlockType blockType) { return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); @@ -487,26 +523,44 @@ public Component getRichItemName(BaseItemStack itemStack) { } @SuppressWarnings({"unchecked", "rawtypes"}) - private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { - if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { - return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else if (state instanceof DirectionProperty) { - return new DirectionalProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - return new EnumProperty(state.getName(), - (List) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); - } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { - return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); - } else { - throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName()); - } - } - }); + private static final LoadingCache> PROPERTY_CACHE = CacheBuilder + .newBuilder() + .build(new CacheLoader>() { + @Override + public Property load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { + if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { + return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else if (state instanceof DirectionProperty) { + return new DirectionalProperty( + state.getName(), + (List) state + .getPossibleValues() + .stream() + .map(e -> Direction.valueOf(((StringRepresentable) e) + .getSerializedName() + .toUpperCase(Locale.ROOT))) + .collect(Collectors.toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { + return new EnumProperty( + state.getName(), + (List) state + .getPossibleValues() + .stream() + .map(e -> ((StringRepresentable) e).getSerializedName()) + .collect(Collectors.toList()) + ); + } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { + return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); + } else { + throw new IllegalArgumentException("WorldEdit needs an update to support " + state + .getClass() + .getSimpleName()); + } + } + }); - @SuppressWarnings({ "rawtypes" }) + @SuppressWarnings({"rawtypes"}) @Override public Map> getProperties(BlockType blockType) { Map> properties = new TreeMap<>(); @@ -520,50 +574,68 @@ public Property load(net.minecraft.world.level.block.state.properties.Propert return properties; } - //FAWE start - CompoundBinaryTag > CompoundTag @Override public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) { - ((CraftPlayer) player).getHandle().networkManager.send(ClientboundBlockEntityDataPacket.create( - new StructureBlockEntity( - new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), - Blocks.STRUCTURE_BLOCK.defaultBlockState() - ), - __ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) + var structureBlock = new StructureBlockEntity( + new BlockPos(pos.getX(), pos.getY(), pos.getZ()), + Blocks.STRUCTURE_BLOCK.defaultBlockState() + ); + structureBlock.setLevel(((CraftPlayer) player).getHandle().level()); + ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create( + structureBlock, + (blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) )); } - //FAWE end @Override public void sendFakeOP(Player player) { - ((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket( + ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket( ((CraftPlayer) player).getHandle(), (byte) 28 )); } @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { - ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); + ItemStack stack = new ItemStack( + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())), + item.getAmount() + ); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()); + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); return CraftItemStack.asCraftMirror(stack); } @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - //FAWE start - CBT > CT - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - //FAWE end - return weStack; + final Tag tag = COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)), + itemStack.getAmount() + ); } + private final LoadingCache fakePlayers + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new)); + @Override public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { CraftWorld craftWorld = (CraftWorld) world; ServerLevel worldServer = craftWorld.getHandle(); - ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack - ? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); - stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); + ItemStack stack = CraftItemStack.asNMSCopy(adapt( + item instanceof BaseItemStack + ? ((BaseItemStack) item) + : new BaseItemStack(item.getType(), item.getNbtReference(), 1) + )); PaperweightFakePlayer fakePlayer; try { @@ -572,20 +644,20 @@ public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, Ba return false; } fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); - fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(), + fakePlayer.absMoveTo(position.getX(), position.getY(), position.getZ(), (float) face.toVector().toYaw(), (float) face.toVector().toPitch() ); - final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + final BlockPos blockPos = new BlockPos(position.getX(), position.getY(), position.getZ()); 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); + InteractionResult result = stack.useOn(context); if (result != InteractionResult.SUCCESS) { if (worldServer .getBlockState(blockPos) - .use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace) + .useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace) .consumesAction()) { result = InteractionResult.SUCCESS; } else { @@ -621,18 +693,18 @@ private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, Environment env = bukkitWorld.getEnvironment(); ChunkGenerator gen = bukkitWorld.getGenerator(); - Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen"); + Path tempDir = Files.createTempDirectory("WorldEditWorldGen"); LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); ResourceKey worldDimKey = getWorldDimKey(env); try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() .getWorldData().overworldData(); - WorldGenSettings originalOpts = levelProperties.worldGenSettings(); + WorldOptions originalOpts = levelProperties.worldGenOptions(); long seed = options.getSeed().orElse(originalWorld.getSeed()); - WorldGenSettings newOpts = options.getSeed().isPresent() - ? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) + WorldOptions newOpts = options.getSeed().isPresent() + ? originalOpts.withSeed(OptionalLong.of(seed)) : originalOpts; LevelSettings newWorldSettings = new LevelSettings( @@ -642,23 +714,40 @@ private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, levelProperties.settings.difficulty(), levelProperties.settings.allowCommands(), levelProperties.settings.gameRules(), - levelProperties.settings.getDataPackConfig() + levelProperties.settings.getDataConfiguration() + ); + + PrimaryLevelData.SpecialWorldProperty specialWorldProperty = + levelProperties.isFlatWorld() + ? PrimaryLevelData.SpecialWorldProperty.FLAT + : levelProperties.isDebugWorld() + ? PrimaryLevelData.SpecialWorldProperty.DEBUG + : PrimaryLevelData.SpecialWorldProperty.NONE; + + PrimaryLevelData newWorldData = new PrimaryLevelData( + newWorldSettings, + newOpts, + specialWorldProperty, + Lifecycle.stable() ); - PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); ServerLevel freshWorld = new ServerLevel( originalWorld.getServer(), originalWorld.getServer().executor, session, newWorldData, originalWorld.dimension(), - originalWorld.dimensionTypeRegistration(), + new LevelStem( + originalWorld.dimensionTypeRegistration(), + originalWorld.getChunkSource().getGenerator() + ), new NoOpWorldLoadListener(), - newOpts.dimensions().get(worldDimKey).generator(), originalWorld.isDebug(), seed, ImmutableList.of(), false, - env, gen, + originalWorld.getRandomSequences(), + env, + gen, bukkitWorld.getBiomeProvider() ); try { @@ -678,7 +767,7 @@ private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, } private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { - ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome); + ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registries.BIOME).getKey(origBiome); if (key == null) { return null; } @@ -721,10 +810,8 @@ private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld Objects.requireNonNull(state); BlockEntity blockEntity = chunk.getBlockEntity(pos); if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); - //FAWE start - BinaryTag + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess()); state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag))); - //FAWE end } extent.setBlock(vec, state.toBaseBlock()); if (options.shouldRegenBiomes()) { @@ -746,9 +833,9 @@ private List> submitChunkLoadTasks(Region region, try { //noinspection unchecked chunkLoadings.add( - ((CompletableFuture>) + ((CompletableFuture>) getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) - .thenApply(either -> either.left().orElse(null)) + .thenApply(either -> either.orElse(null)) ); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Couldn't load chunk for regen.", e); @@ -769,6 +856,15 @@ private ResourceKey getWorldDimKey(Environment env) { } } + 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; @@ -797,7 +893,6 @@ public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 * @param foreign non-native NMS NBT structure * @return native WorldEdit NBT structure */ - //FAWE start - BinaryTag @Override public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { if (foreign == null) { @@ -830,7 +925,7 @@ public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { try { return toNativeList((net.minecraft.nbt.ListTag) foreign); } catch (Throwable e) { - LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); + logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); return ListBinaryTag.empty(); } } else if (foreign instanceof net.minecraft.nbt.LongTag) { @@ -855,7 +950,7 @@ public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { * @throws IllegalArgumentException on error */ private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { - ListBinaryTag.Builder values = ListBinaryTag.builder(); + ListBinaryTag.Builder values = ListBinaryTag.builder(); for (net.minecraft.nbt.Tag tag : foreign) { values.add(toNativeBinary(tag)); @@ -895,8 +990,9 @@ public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) { return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); } else if (foreign instanceof LongArrayBinaryTag) { return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); - } else if (foreign instanceof ListBinaryTag foreignList) { + } else if (foreign instanceof ListBinaryTag) { net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); + ListBinaryTag foreignList = (ListBinaryTag) foreign; for (BinaryTag t : foreignList) { tag.add(fromNativeBinary(t)); } @@ -913,7 +1009,6 @@ public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) { throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); } } - //FAWE end @Override public boolean supportsWatchdog() { @@ -925,6 +1020,35 @@ 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; @@ -933,8 +1057,11 @@ private static class MojangWatchdog implements Watchdog { MojangWatchdog(DedicatedServer server) throws NoSuchFieldException { this.server = server; Field tickField = MinecraftServer.class.getDeclaredField( - Refraction.pickName("nextTickTime", "ao") + Refraction.pickName("nextTickTime", "ah") ); + if (tickField.getType() != long.class) { + throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect"); + } tickField.setAccessible(true); this.tickField = tickField; } @@ -956,7 +1083,11 @@ public void updateSpawnPos(ChunkPos spawnPos) { } @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { + public void onStatusChange( + final ChunkPos pos, + @org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status + ) { + } @Override @@ -967,39 +1098,6 @@ public void start() { public void stop() { } - @Override - public void setChunkRadius(int radius) { - } - - } - - 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); - } - } - } } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java similarity index 94% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java index 84cae3e579..39807b86d5 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightDataConverters.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -29,18 +29,21 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; +import com.mojang.datafixers.DSL; import com.mojang.datafixers.DSL.TypeReference; import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; +import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import net.minecraft.core.Direction; import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.StringTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.TextComponent; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.GsonHelper; import net.minecraft.util.StringUtil; import net.minecraft.util.datafix.DataFixers; @@ -66,150 +69,74 @@ /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) - *

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

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

+ * * This class also provides util methods for converting compounds to wrap the update call to * receive the source version in the compound */ -@SuppressWarnings({"rawtypes", "unchecked"}) -class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { +@SuppressWarnings({ "rawtypes", "unchecked" }) +public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { - private static final NbtOps OPS_NBT = NbtOps.INSTANCE; - private static final int LEGACY_VERSION = 1343; - private static final Map DFU_TO_LEGACY = new HashMap<>(); - private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); - static PaperweightDataConverters INSTANCE; - private static int DATA_VERSION; + //FAWE start - BinaryTag + @SuppressWarnings("unchecked") + @Override + public T fixUp(FixType type, T original, int srcVer) { + if (type == FixTypes.CHUNK) { + return (T) fixChunk((CompoundBinaryTag) original, srcVer); + } else if (type == FixTypes.BLOCK_ENTITY) { + return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); + } else if (type == FixTypes.ENTITY) { + return (T) fixEntity((CompoundBinaryTag) original, srcVer); + } else if (type == FixTypes.BLOCK_STATE) { + return (T) fixBlockState((String) original, srcVer); + } else if (type == FixTypes.ITEM_TYPE) { + return (T) fixItemType((String) original, srcVer); + } else if (type == FixTypes.BIOME) { + return (T) fixBiome((String) original, srcVer); + } + return original; + } - 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 CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); + return (CompoundBinaryTag) adapter.toNativeBinary(fixed); } - private final PaperweightAdapter adapter; - private final Map> converters = new EnumMap<>(LegacyType.class); - private final Map> inspectors = new EnumMap<>(LegacyType.class); - // Set on build - private DataFixer fixer; + private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); + return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + } - PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { - super(dataVersion); - DATA_VERSION = dataVersion; - INSTANCE = this; - this.adapter = adapter; - registerConverters(); - registerInspectors(); + private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { + net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); + net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); + return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + } + //FAWE end + + private String fixBlockState(String blockState, int srcVer) { + net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); + Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); + net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); + return nbtToState(fixed); + } + + private String nbtToState(net.minecraft.nbt.CompoundTag tagCompound) { + StringBuilder sb = new StringBuilder(); + sb.append(tagCompound.getString("Name")); + if (tagCompound.contains("Properties", 10)) { + sb.append('['); + net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties"); + sb.append(props.getAllKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(","))); + sb.append(']'); + } + return sb.toString(); } private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { @@ -231,167 +158,166 @@ private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { 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(); } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { - return convert(type.getDFUType(), cmp); - } + private final PaperweightAdapter adapter; - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type.getDFUType(), cmp, sourceVer); - } + private static final NbtOps OPS_NBT = NbtOps.INSTANCE; + private static final int LEGACY_VERSION = 1343; + private static int DATA_VERSION; + public static PaperweightDataConverters INSTANCE; - 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); + 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; + } } - 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 PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { + super(dataVersion); + DATA_VERSION = dataVersion; + INSTANCE = this; + this.adapter = adapter; + registerConverters(); + registerInspectors(); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type, cmp, sourceVer, DATA_VERSION); + + // Called after fixers are built and ready for FIXING + @Override + public DataFixer buildUnoptimized() { + return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); } - 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(); + @Override + public DataFixer buildOptimized(final Set requiredTypes, Executor executor) { + return buildUnoptimized(); } - 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); + @SuppressWarnings("unchecked") + private class WrappedDataFixer implements DataFixer { + private final DataFixer realFixer; + + WrappedDataFixer(DataFixer realFixer) { + this.realFixer = realFixer; } - 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)); - } + @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); - 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); + cmp = convert(legacyType, cmp, sourceVer, desiredVersion); + sourceVer = desiredVersion; + dynamic = new Dynamic(OPS_NBT, cmp); + } + return realFixer.update(type, dynamic, 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); + 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); + } + } + } - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); + 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); + } } - //FAWE start - CBT > CT - @SuppressWarnings("unchecked") - @Override - public T fixUp(FixType type, T original, int srcVer) { - if (type == FixTypes.CHUNK) { - return (T) fixChunk((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((CompoundBinaryTag) original, srcVer); - } else if (type == FixTypes.BLOCK_STATE) { - return (T) fixBlockState((String) original, srcVer); - } else if (type == FixTypes.ITEM_TYPE) { - return (T) fixItemType((String) original, srcVer); - } else if (type == FixTypes.BIOME) { - return (T) fixBiome((String) original, srcVer); - } - return original; + public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { + return convert(type.getDFUType(), cmp); } - private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + return convert(type.getDFUType(), cmp, sourceVer); } - private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + 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); } - private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return (CompoundBinaryTag) adapter.toNativeBinary(fixed); + 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); } - //FAWE end - private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update( - References.BLOCK_STATE, - dynamic, - srcVer, - DATA_VERSION - ).getValue(); - return nbtToState(fixed); + public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + return convert(type, cmp, sourceVer, DATA_VERSION); } - 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(']'); + public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + if (sourceVer >= targetVer) { + return cmp; } - return sb.toString(); + return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); } - 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); + public interface DataInspector { + net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); } - // Called after fixers are built and ready for FIXING - @Override - public DataFixer build(final Executor executor) { - return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); + 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); } @@ -536,47 +462,154 @@ 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 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 void registerEntityItemListEquipment(String type) { - registerEntityItemList(type, "ArmorItems", "HandItems"); + 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)); } - 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; + 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); } } - public interface DataInspector { - - net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); - - } - - public interface DataConverter { - - int getDataVersion(); + 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); - net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); + for (int j = 0; j < nbttaglist.size(); ++j) { + nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompound(j), sourceVer, targetVer)); + } + } } @@ -635,7 +668,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataInspectorBlockEntity implements DataInspector { @@ -643,6 +675,50 @@ 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; @@ -734,56 +810,10 @@ private static class DataInspectorBlockEntity implements DataInspector { map.put("minecraft:end_gateway", "minecraft:end_gateway"); map.put("minecraft:shield", "minecraft:shield"); } - - DataInspectorBlockEntity() { - } - - @Nullable - private static String convertEntityId(int i, String s) { - String key = new ResourceLocation(s).toString(); - if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { - return DataInspectorBlockEntity.b.get(key); - } else { - return DataInspectorBlockEntity.c.get(key); - } - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (!cmp.contains("tag", 10)) { - return cmp; - } else { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - - if (nbttagcompound1.contains("BlockEntityTag", 10)) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("BlockEntityTag"); - String s = cmp.getString("id"); - String s1 = convertEntityId(sourceVer, s); - boolean flag; - - if (s1 == null) { - // CraftBukkit - Remove unnecessary warning (occurs when deserializing a Shulker Box item) - // DataInspectorBlockEntity.a.warn("Unable to resolve BlockEntity for ItemInstance: {}", s); - flag = false; - } else { - flag = !nbttagcompound2.contains("id"); - nbttagcompound2.putString("id", s1); - } - - convert(LegacyType.BLOCK_ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - } - - return cmp; - } - } } private static class DataInspectorEntity implements DataInspector { - private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class); - DataInspectorEntity() { } @@ -818,9 +848,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - } + private abstract static class DataInspectorTagged implements DataInspector { private final ResourceLocation key; @@ -837,12 +867,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - abstract net.minecraft.nbt.CompoundTag inspectChecked( - net.minecraft.nbt.CompoundTag 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 { @@ -861,7 +886,6 @@ net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbtta return nbttagcompound; } - } private static class DataInspectorItem extends DataInspectorTagged { @@ -880,13 +904,31 @@ net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbtta 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"; @@ -1244,25 +1286,6 @@ private static class DataConverterMaterialId implements DataConverter { materials[453] = "minecraft:knowledge_book"; // Paper end } - - DataConverterMaterialId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.contains("id", 99)) { - short short0 = cmp.getShort("id"); - - if (short0 > 0 && short0 < materials.length && materials[short0] != null) { - cmp.putString("id", materials[short0]); - } - } - - return cmp; - } } private static class DataConverterArmorStand implements DataConverter { @@ -1281,7 +1304,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterBanner implements DataConverter { @@ -1328,13 +1350,42 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) 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"; @@ -1465,26 +1516,32 @@ private static class DataConverterPotionId implements DataConverter { DataConverterPotionId.potions[126] = "minecraft:long_invisibility"; DataConverterPotionId.potions[127] = null; } + } - DataConverterPotionId() { + private static class DataConverterSpawnEgg implements DataConverter { + + private static final String[] eggs = new String[256]; + + DataConverterSpawnEgg() { } public int getDataVersion() { - return 102; + return 105; } public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:potion".equals(cmp.getString("id"))) { + 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 (!nbttagcompound1.contains("Potion", 8)) { - String s = DataConverterPotionId.potions[short0 & 127]; + if (!nbttagcompound2.contains("id", 8)) { + String s = DataConverterSpawnEgg.eggs[short0 & 255]; - nbttagcompound1.putString("Potion", s == null ? "minecraft:water" : s); - cmp.put("tag", nbttagcompound1); - if ((short0 & 16384) == 16384) { - cmp.putString("id", "minecraft:splash_potion"); + if (s != null) { + nbttagcompound2.putString("id", s); + nbttagcompound1.put("EntityTag", nbttagcompound2); + cmp.put("tag", nbttagcompound1); } } @@ -1495,11 +1552,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } - - private static class DataConverterSpawnEgg implements DataConverter { - - private static final String[] eggs = new String[256]; static { @@ -1571,50 +1623,11 @@ private static class DataConverterSpawnEgg implements DataConverter { DataConverterSpawnEgg.eggs[120] = "Villager"; DataConverterSpawnEgg.eggs[200] = "EnderCrystal"; } - - DataConverterSpawnEgg() { - } - - public int getDataVersion() { - return 105; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:spawn_egg".equals(cmp.getString("id"))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("EntityTag"); - short short0 = cmp.getShort("Damage"); - - if (!nbttagcompound2.contains("id", 8)) { - String s = DataConverterSpawnEgg.eggs[short0 & 255]; - - if (s != null) { - nbttagcompound2.putString("id", s); - nbttagcompound1.put("EntityTag", nbttagcompound2); - cmp.put("tag", nbttagcompound1); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } } private static class DataConverterMinecart implements DataConverter { - private static final List a = Lists.newArrayList( - "MinecartRideable", - "MinecartChest", - "MinecartFurnace", - "MinecartTNT", - "MinecartSpawner", - "MinecartHopper", - "MinecartCommandBlock" - ); + private static final List a = Lists.newArrayList("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock"); DataConverterMinecart() { } @@ -1638,7 +1651,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterMobSpawner implements DataConverter { @@ -1683,7 +1695,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } } - } private static class DataConverterUUID implements DataConverter { @@ -1702,47 +1713,11 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterHealth implements DataConverter { - private static final Set a = Sets.newHashSet( - "ArmorStand", - "Bat", - "Blaze", - "CaveSpider", - "Chicken", - "Cow", - "Creeper", - "EnderDragon", - "Enderman", - "Endermite", - "EntityHorse", - "Ghast", - "Giant", - "Guardian", - "LavaSlime", - "MushroomCow", - "Ozelot", - "Pig", - "PigZombie", - "Rabbit", - "Sheep", - "Shulker", - "Silverfish", - "Skeleton", - "Slime", - "SnowMan", - "Spider", - "Squid", - "Villager", - "VillagerGolem", - "Witch", - "WitherBoss", - "Wolf", - "Zombie" - ); + private static final Set a = Sets.newHashSet("ArmorStand", "Bat", "Blaze", "CaveSpider", "Chicken", "Cow", "Creeper", "EnderDragon", "Enderman", "Endermite", "EntityHorse", "Ghast", "Giant", "Guardian", "LavaSlime", "MushroomCow", "Ozelot", "Pig", "PigZombie", "Rabbit", "Sheep", "Shulker", "Silverfish", "Skeleton", "Slime", "SnowMan", "Spider", "Squid", "Villager", "VillagerGolem", "Witch", "WitherBoss", "Wolf", "Zombie"); DataConverterHealth() { } @@ -1771,7 +1746,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterSaddle implements DataConverter { @@ -1796,7 +1770,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterHanging implements DataConverter { @@ -1835,7 +1808,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterDropChances implements DataConverter { @@ -1859,15 +1831,13 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (cmp.contains("ArmorDropChances", 9)) { nbttaglist = cmp.getList("ArmorDropChances", 5); - if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat( - 2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { + if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) { cmp.remove("ArmorDropChances"); } } return cmp; } - } private static class DataConverterRiding implements DataConverter { @@ -1903,7 +1873,6 @@ protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagco nbttagcompound.remove("Riding"); return nbttagcompound1; } - } private static class DataConverterBook implements DataConverter { @@ -1928,39 +1897,42 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) 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); + object = Component.literal(s); } else { try { object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); if (object == null) { - object = new TextComponent(""); + object = Component.literal(""); } - } catch (JsonParseException ignored) { + } catch (JsonParseException jsonparseexception) { + ; } if (object == null) { try { - object = Component.Serializer.fromJson(s); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJson(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; } } if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJsonLenient(s, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; } } if (object == null) { - object = new TextComponent(s); + object = Component.literal(s); } } } else { - object = new TextComponent(""); + object = Component.literal(""); } - nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); + nbttaglist.set(i, StringTag.valueOf(Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess()))); } nbttagcompound1.put("pages", nbttaglist); @@ -1969,7 +1941,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterCookedFish implements DataConverter { @@ -1990,7 +1961,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterZombie implements DataConverter { @@ -2012,7 +1982,8 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (cmp.contains("VillagerProfession", 99)) { try { i = this.convert(cmp.getInt("VillagerProfession")); - } catch (RuntimeException ignored) { + } catch (RuntimeException runtimeexception) { + ; } } @@ -2032,7 +2003,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) private int convert(int i) { return i >= 0 && i < 6 ? i : -1; } - } private static class DataConverterVBO implements DataConverter { @@ -2048,7 +2018,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) cmp.putString("useVbo", "true"); return cmp; } - } private static class DataConverterGuardian implements DataConverter { @@ -2071,7 +2040,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterSkeleton implements DataConverter { @@ -2100,7 +2068,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterZombieType implements DataConverter { @@ -2139,7 +2106,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterHorse implements DataConverter { @@ -2182,13 +2148,29 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) 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"); @@ -2214,8 +2196,13 @@ private static class DataConverterTileEntity implements DataConverter { DataConverterTileEntity.a.put("Structure", "minecraft:structure_block"); DataConverterTileEntity.a.put("Trap", "minecraft:dispenser"); } + } - DataConverterTileEntity() { + private static class DataConverterEntity implements DataConverter { + + private static final Map a = Maps.newHashMap(); + + DataConverterEntity() { } public int getDataVersion() { @@ -2223,7 +2210,7 @@ public int getDataVersion() { } public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterTileEntity.a.get(cmp.getString("id")); + String s = DataConverterEntity.a.get(cmp.getString("id")); if (s != null) { cmp.putString("id", s); @@ -2231,11 +2218,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } - - private static class DataConverterEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); static { DataConverterEntity.a.put("AreaEffectCloud", "minecraft:area_effect_cloud"); @@ -2314,23 +2296,6 @@ private static class DataConverterEntity implements DataConverter { DataConverterEntity.a.put("ZombieHorse", "minecraft:zombie_horse"); DataConverterEntity.a.put("ZombieVillager", "minecraft:zombie_villager"); } - - DataConverterEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterEntity.a.get(cmp.getString("id")); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } } private static class DataConverterPotionWater implements DataConverter { @@ -2345,8 +2310,7 @@ public int getDataVersion() { 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)) { + 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)) { @@ -2360,7 +2324,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterShulker implements DataConverter { @@ -2379,12 +2342,11 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterShulkerBoxItem implements DataConverter { - public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"}; + public static final String[] a = new String[] { "minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box" }; DataConverterShulkerBoxItem() { } @@ -2421,7 +2383,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterShulkerBoxBlock implements DataConverter { @@ -2440,7 +2401,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterLang implements DataConverter { @@ -2459,7 +2419,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterTotem implements DataConverter { @@ -2478,7 +2437,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterBedBlock implements DataConverter { @@ -2526,7 +2484,6 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterBedItem implements DataConverter { @@ -2545,26 +2502,22 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) return cmp; } - } private static class DataConverterSignText implements DataConverter { public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { - MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws - JsonParseException { + MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { if (jsonelement.isJsonPrimitive()) { - return new TextComponent(jsonelement.getAsString()); + return Component.literal(jsonelement.getAsString()); } else if (jsonelement.isJsonArray()) { JsonArray jsonarray = jsonelement.getAsJsonArray(); MutableComponent ichatbasecomponent = null; + Iterator iterator = jsonarray.iterator(); - for (final JsonElement jsonelement1 : jsonarray) { - MutableComponent ichatbasecomponent1 = this.a( - jsonelement1, - jsonelement1.getClass(), - jsondeserializationcontext - ); + while (iterator.hasNext()) { + JsonElement jsonelement1 = (JsonElement) iterator.next(); + MutableComponent ichatbasecomponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); if (ichatbasecomponent == null) { ichatbasecomponent = ichatbasecomponent1; @@ -2579,11 +2532,7 @@ MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContex } } - public Object deserialize( - JsonElement jsonelement, - Type type, - JsonDeserializationContext jsondeserializationcontext - ) throws JsonParseException { + public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { return this.a(jsonelement, type, jsondeserializationcontext); } }).create(); @@ -2612,45 +2561,46 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { 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); + object = Component.literal(s1); } else { try { object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); if (object == null) { - object = new TextComponent(""); + object = Component.literal(""); } - } catch (JsonParseException ignored) { + } catch (JsonParseException jsonparseexception) { + ; } if (object == null) { try { - object = Component.Serializer.fromJson(s1); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJson(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception1) { + ; } } if (object == null) { try { - object = Component.Serializer.fromJsonLenient(s1); - } catch (JsonParseException ignored) { + object = Component.Serializer.fromJsonLenient(s1, MinecraftServer.getServer().registryAccess()); + } catch (JsonParseException jsonparseexception2) { + ; } } if (object == null) { - object = new TextComponent(s1); + object = Component.literal(s1); } } } else { - object = new TextComponent(""); + object = Component.literal(""); } - nbttagcompound.putString(s, Component.Serializer.toJson(object)); + nbttagcompound.putString(s, Component.Serializer.toJson(object, MinecraftServer.getServer().registryAccess())); } - } private static class DataInspectorPlayerVehicle implements DataInspector { - @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.contains("RootVehicle", 10)) { @@ -2663,11 +2613,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, 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)) { @@ -2676,11 +2624,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, 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; @@ -2711,11 +2657,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, 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)) { @@ -2727,14 +2671,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, nbttaglist = nbttagcompound1.getList("Entities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert(LegacyType.ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); + nbttaglist.set(j, convert(LegacyType.ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); } } @@ -2742,25 +2679,16 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, nbttaglist = nbttagcompound1.getList("TileEntities", 10); for (j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set( - j, - convert(LegacyType.BLOCK_ENTITY, - (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), - sourceVer, - targetVer - ) - ); + nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (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)) { @@ -2773,11 +2701,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, 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); @@ -2792,11 +2718,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - } private static class DataInspectorVillagers implements DataInspector { - ResourceLocation entityVillager = getKey("EntityVillager"); @Override @@ -2820,11 +2744,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - } private static class DataInspectorMobSpawnerMinecart implements DataInspector { - ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @@ -2839,11 +2761,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - } private static class DataInspectorMobSpawnerMobs implements DataInspector { - ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override @@ -2864,11 +2784,9 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - } private static class DataInspectorCommandBlock implements DataInspector { - ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); @Override @@ -2881,63 +2799,5 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, return cmp; } - - } - - @SuppressWarnings("unchecked") - private class WrappedDataFixer implements DataFixer { - - private final DataFixer realFixer; - - WrappedDataFixer(DataFixer realFixer) { - this.realFixer = realFixer; - } - - @Override - public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { - LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); - if (sourceVer < LEGACY_VERSION && legacyType != null) { - net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); - int desiredVersion = Math.min(targetVer, LEGACY_VERSION); - - cmp = convert(legacyType, cmp, sourceVer, desiredVersion); - sourceVer = desiredVersion; - dynamic = new Dynamic(OPS_NBT, cmp); - } - return realFixer.update(type, dynamic, sourceVer, targetVer); - } - - private net.minecraft.nbt.CompoundTag convert( - LegacyType type, - net.minecraft.nbt.CompoundTag cmp, - int sourceVer, - int desiredVersion - ) { - List converters = PaperweightDataConverters.this.converters.get(type); - if (converters != null && !converters.isEmpty()) { - for (DataConverter converter : converters) { - int dataVersion = converter.getDataVersion(); - if (dataVersion > sourceVer && dataVersion <= desiredVersion) { - cmp = converter.convert(cmp); - } - } - } - - List inspectors = PaperweightDataConverters.this.inspectors.get(type); - if (inspectors != null && !inspectors.isEmpty()) { - for (DataInspector inspector : inspectors) { - cmp = inspector.inspect(cmp, sourceVer, desiredVersion); - } - } - - return cmp; - } - - @Override - public Schema getSchema(int i) { - return realFixer.getSchema(i); - } - } - } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java similarity index 78% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java index e5ff266727..792942843b 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightFakePlayer.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightFakePlayer.java @@ -17,18 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.mojang.authlib.GameProfile; -import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stat; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -37,15 +38,14 @@ import java.util.UUID; class PaperweightFakePlayer extends ServerPlayer { - - private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( - UUID.nameUUIDFromBytes("worldedit".getBytes()), - "[WorldEdit]" - ); + private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]"); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); + private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( + "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false + ); PaperweightFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); + super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } @Override @@ -72,17 +72,13 @@ public OptionalInt openMenu(MenuProvider factory) { } @Override - public void updateOptions(ServerboundClientInformationPacket packet) { + public void updateOptions(ClientInformation clientOptions) { } @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) { } @@ -97,7 +93,6 @@ public boolean isInvulnerableTo(DamageSource damageSource) { } @Override - public void openTextEdit(SignBlockEntity sign) { + public void openTextEdit(SignBlockEntity sign, boolean front) { } - } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java similarity index 74% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java index e9656539ab..f7e5cee3f9 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -27,21 +27,19 @@ import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BlockState; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.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 { - +public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; private static final int NOTIFY = 2; @@ -83,19 +81,12 @@ public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk @Nullable @Override - public net.minecraft.world.level.block.state.BlockState setBlockState( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState state - ) { + public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) { return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); } @Override - public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( - net.minecraft.world.level.block.state.BlockState block, - BlockPos position - ) { + public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) { return Block.updateFromNeighbourShapes(block, getWorld(), position); } @@ -115,12 +106,7 @@ public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag } @Override - public void notifyBlockUpdate( - LevelChunk chunk, - BlockPos position, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); } @@ -128,7 +114,7 @@ public void notifyBlockUpdate( @Override public boolean isChunkTicking(LevelChunk chunk) { - return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); } @Override @@ -139,11 +125,7 @@ public void markBlockChanged(LevelChunk chunk, BlockPos position) { } @Override - public void notifyNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { ServerLevel world = getWorld(); if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { world.updateNeighborsAt(pos, oldState.getBlock()); @@ -162,27 +144,20 @@ public void notifyNeighbors( } } + // Not sure why neighborChanged is deprecated private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { - world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false); + world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false); } @Override - public void updateNeighbors( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState, - int recursionLimit - ) { + public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) { ServerLevel world = getWorld(); // a == updateNeighbors // b == updateDiagonalNeighbors oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { CraftWorld craftWorld = world.getWorld(); - BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), - CraftBlockData.fromData(newState) - ); + BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState)); world.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; @@ -193,19 +168,13 @@ public void updateNeighbors( } @Override - public void onBlockStateChange( - BlockPos pos, - net.minecraft.world.level.block.state.BlockState oldState, - net.minecraft.world.level.block.state.BlockState newState - ) { + public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) { getWorld().onBlockStateChange(pos, oldState, newState); } - //FAWE start @Override public void flush() { } - //FAWE end } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java similarity index 69% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java index b5da62e0fd..9c22924514 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java @@ -1,28 +1,24 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.util.ReflectionUtil; -import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.PushReaction; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.block.data.CraftBlockData; public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; private final BlockState blockState; - private final Material material; - private final boolean isTranslucent; private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; @@ -35,22 +31,16 @@ public PaperweightBlockMaterial(Block block) { public PaperweightBlockMaterial(Block block, BlockState blockState) { this.block = block; this.blockState = blockState; - this.material = blockState.getMaterial(); this.craftBlockData = CraftBlockData.fromData(blockState); this.craftMaterial = craftBlockData.getMaterial(); - BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName( - "properties", "aO")); - this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo, - Refraction.pickName("canOcclude", "n") - ); opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( BlockPos.ZERO, blockState ); - tile = tileEntity == null - ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + tile = tileEntity == null ? null : new PaperweightLazyCompoundTag( + Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); } public Block getBlock() { @@ -65,10 +55,6 @@ public CraftBlockData getCraftBlockData() { return craftBlockData; } - public Material getMaterial() { - return material; - } - @Override public boolean isAir() { return blockState.isAir(); @@ -81,7 +67,7 @@ public boolean isFullCube() { @Override public boolean isOpaque() { - return material.isSolidBlocking(); + return blockState.canOcclude(); } @Override @@ -91,12 +77,13 @@ public boolean isPowerSource() { @Override public boolean isLiquid() { - return material.isLiquid(); + return !blockState.getFluidState().is(Fluids.EMPTY); } @Override public boolean isSolid() { - return material.isSolid(); + // No access to world -> EmptyBlockGetter + return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); } @Override @@ -126,27 +113,27 @@ public int getLightOpacity() { @Override public boolean isFragileWhenPushed() { - return material.getPushReaction() == PushReaction.DESTROY; + return blockState.getPistonPushReaction() == PushReaction.DESTROY; } @Override public boolean isUnpushable() { - return material.getPushReaction() == PushReaction.BLOCK; + return blockState.getPistonPushReaction() == PushReaction.BLOCK; } @Override public boolean isTicksRandomly() { - return block.isRandomlyTicking(blockState); + return blockState.isRandomlyTicking(); } @Override public boolean isMovementBlocker() { - return material.isSolid(); + return craftMaterial.isSolid(); } @Override public boolean isBurnable() { - return material.isFlammable(); + return craftMaterial.isBurnable(); } @Override @@ -157,12 +144,12 @@ public boolean isToolRequired() { @Override public boolean isReplacedDuringPlacement() { - return material.isReplaceable(); + return blockState.canBeReplaced(); } @Override public boolean isTranslucent() { - return isTranslucent; + return !blockState.canOcclude(); } @Override @@ -183,7 +170,7 @@ public CompoundTag getDefaultTile() { @Override public int getMapColor() { // rgb field - return material.getColor().col; + return block.defaultMapColor().col; } } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java similarity index 82% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java index 8b96e2ea6b..b263c9ced6 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; @@ -12,14 +12,13 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Codec; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen.PaperweightRegen; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen.PaperweightRegen; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -35,6 +34,7 @@ import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; @@ -45,7 +45,6 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemType; @@ -53,44 +52,48 @@ import io.papermc.lib.PaperLib; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; -import net.minecraft.nbt.IntTag; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.StringRepresentable; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_18_R2.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.entity.Player; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -104,11 +107,24 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static net.minecraft.core.registries.Registries.BIOME; + public final class PaperweightFaweAdapter extends FaweAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; + private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( + "components", DataComponentPatch.EMPTY + ).codec(); + + static { + try { + CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave"); + } catch (NoSuchMethodException ignored) { // may not be present in newer paper versions + } + } - private final PaperweightAdapter parent; + private final com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter parent; // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ @@ -119,7 +135,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter>> allBlockProperties = null; public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { - this.parent = new PaperweightAdapter(); + this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter(); } @Nullable @@ -128,6 +144,10 @@ private static String getEntityId(Entity entity) { return resourceLocation == null ? null : resourceLocation.toString(); } + private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { + entity.save(compoundTag); + } + @Override public BukkitImplAdapter getParent() { return parent; @@ -219,7 +239,8 @@ public synchronized BlockMaterial getMaterial(BlockState state) { } public Block getBlock(BlockType blockType) { - return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); + return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK) + .get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); } @Deprecated @@ -264,7 +285,7 @@ public BaseBlock getFullBlock(final Location location) { // Read the NBT data BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); + net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); } } @@ -277,54 +298,6 @@ public Set getSupportedSideEffects() { return SideEffectSet.defaults().getSideEffectsToApply(); } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { - CraftChunk craftChunk = (CraftChunk) chunk; - LevelChunk levelChunk = craftChunk.getHandle(); - Level level = levelChunk.getLevel(); - - BlockPos blockPos = new BlockPos(x, y, z); - net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState(); - LevelChunkSection[] levelChunkSections = levelChunk.getSections(); - int y4 = y >> 4; - LevelChunkSection section = levelChunkSections[y4]; - - net.minecraft.world.level.block.state.BlockState existing; - if (section == null) { - existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); - } else { - existing = section.getBlockState(x & 15, y & 15, z & 15); - } - - levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity - - CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null; - if (compoundTag != null || existing instanceof TileEntityBlock) { - level.setBlock(blockPos, blockState, 0); - // remove tile - if (compoundTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - BlockEntity blockEntity = level.getBlockEntity(blockPos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag); - tag.put("x", IntTag.valueOf(x)); - tag.put("y", IntTag.valueOf(y)); - tag.put("z", IntTag.valueOf(z)); - blockEntity.load(tag); // readTagIntoTileEntity - load data - } - } - } else { - if (existing == blockState) { - return true; - } - levelChunk.setBlockState(blockPos, blockState, false); - } - if (update) { - level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0); - } - return true; - } - @Override public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); @@ -343,7 +316,7 @@ public BaseEntity getEntity(org.bukkit.entity.Entity entity) { EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); + readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); @@ -474,7 +447,8 @@ public > BlockData adapt(B state) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { ServerLevel nmsWorld = getServerLevel(world); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); - if (map != null && map.wasAccessibleSinceLastSave()) { + if (map != null && wasAccessibleSinceLastSave(map)) { + boolean flag = false; // PlayerChunk.d players = map.players; Stream stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) */ Stream.empty(); @@ -516,11 +490,18 @@ public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, Blo @Override public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); ItemStack stack = new ItemStack( - Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), + registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().getId())), baseItemStack.getAmount() ); - stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); + final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()); + if (nbt != null) { + final DataComponentPatch patch = COMPONENTS_CODEC + .parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt) + .getOrThrow(); + stack.applyComponents(patch); + } return CraftItemStack.asCraftMirror(stack); } @@ -547,29 +528,19 @@ protected ServerLevel getServerLevel(final World world) { return ((CraftWorld) world).getHandle(); } - @Override - public List getEntities(org.bukkit.World world) { - // Quickly add each entity to a list copy. - List mcEntities = new ArrayList<>(); - getServerLevel(world).entityManager.getEntityGetter().getAll().forEach(mcEntities::add); - - List list = new ArrayList<>(); - mcEntities.forEach((mcEnt) -> { - org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); - if (bukkitEntity.isValid()) { - list.add(bukkitEntity); - } - - }); - return list; - } - @Override public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { + final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess(); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); - final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); - weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); - return weStack; + final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart( + registryAccess.createSerializationContext(NbtOps.INSTANCE), + nmsStack.getComponentsPatch() + ).getOrThrow(); + return new BaseItemStack( + BukkitAdapter.asItemType(itemStack.getType()), + LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)), + itemStack.getAmount() + ); } @Override @@ -577,17 +548,12 @@ public Tag toNative(net.minecraft.nbt.Tag foreign) { return parent.toNative(foreign); } - @Override - public BinaryTag toNativeBinary(final net.minecraft.nbt.Tag foreign) { - return parent.toNativeBinary(foreign); - } - @Override public net.minecraft.nbt.Tag fromNative(Tag foreign) { if (foreign instanceof PaperweightLazyCompoundTag) { return ((PaperweightLazyCompoundTag) foreign).get(); } - return (net.minecraft.nbt.Tag) parent.fromNative(foreign); + return parent.fromNative(foreign); } @Override @@ -605,7 +571,7 @@ public int getInternalBiomeId(BiomeType biomeType) { final Registry registry = MinecraftServer .getServer() .registryAccess() - .ownedRegistryOrThrow(Registry.BIOME_REGISTRY); + .registryOrThrow(BIOME); ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); Biome biome = registry.get(resourceLocation); return registry.getId(biome); @@ -616,8 +582,7 @@ public Iterable getRegisteredBiomes() { WritableRegistry biomeRegistry = (WritableRegistry) ((CraftServer) Bukkit.getServer()) .getServer() .registryAccess() - .ownedRegistryOrThrow( - Registry.BIOME_REGISTRY); + .registryOrThrow(BIOME); List keys = biomeRegistry.stream() .map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); List namespacedKeys = new ArrayList<>(); @@ -659,4 +624,16 @@ public IBatchProcessor getTickingPostProcessor() { return new PaperweightPostProcessor(); } + private boolean wasAccessibleSinceLastSave(ChunkHolder holder) { + if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) { + try { + return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder); + } catch (IllegalAccessException | InvocationTargetException ignored) { + // fall-through + } + } + // Papers new chunk system has no related replacement - therefor we assume true. + return true; + } + } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java similarity index 94% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java index ef7fc98ac0..6479ff53c1 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweWorldNativeAccess.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; @@ -15,14 +15,15 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; import javax.annotation.Nullable; @@ -102,7 +103,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta } // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ())); + cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ)); boolean nextTick = lastTick.get() > currentTick; if (nextTick || cachedChanges.size() >= 1024) { if (nextTick) { @@ -140,7 +141,7 @@ public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) { return false; } net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag); - blockEntity.load((CompoundTag) nativeTag); + blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess()); return true; } @@ -157,7 +158,7 @@ public void notifyBlockUpdate( @Override public boolean isChunkTicking(LevelChunk levelChunk) { - return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); } @Override @@ -181,7 +182,7 @@ public void notifyNeighbors( // Un-nest neighbour updating for (Direction direction : NEIGHBOUR_ORDER) { BlockPos shifted = blockPos.relative(direction); - level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false); + level.getBlockState(shifted).handleNeighborChanged(level, shifted, oldState.getBlock(), blockPos, false); } } if (newState.hasAnalogOutputSignal()) { diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java similarity index 94% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java index 7291c0f691..41639d67df 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks; import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; @@ -20,7 +20,7 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -29,12 +29,9 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import io.papermc.paper.event.block.BeaconDeactivatedEvent; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.IdMap; -import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; +import net.minecraft.core.*; import net.minecraft.nbt.IntTag; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.BitStorage; @@ -46,33 +43,17 @@ import net.minecraft.world.level.block.entity.BeaconBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.DataLayer; -import net.minecraft.world.level.chunk.HashMapPalette; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.LinearPalette; -import net.minecraft.world.level.chunk.Palette; -import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.*; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.lighting.LevelLightEngine; import org.apache.logging.log4j.Logger; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; import javax.annotation.Nonnull; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; @@ -83,13 +64,16 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static net.minecraft.core.registries.Registries.BIOME; + public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + private static final Function nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag( + Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); @@ -130,7 +114,7 @@ public PaperweightGetBlocks(ServerLevel serverLevel, int chunkX, int chunkZ) { this.maxSectionPosition = maxHeight >> 4; this.skyLight = new DataLayer[getSectionCount()]; this.blockLight = new DataLayer[getSectionCount()]; - this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); + this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); } @@ -260,7 +244,7 @@ public CompoundTag getTile(int x, int y, int z) { if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))); } @Override @@ -289,8 +273,7 @@ public int getSkyLight(int x, int y, int z) { ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( LightLayer.BLOCK, sectionPos, - dataLayer, - true + dataLayer ); } skyLight[alayer] = dataLayer; @@ -317,7 +300,7 @@ public int getEmittedLight(int x, int y, int z) { Arrays.fill(LAYER_COUNT, (byte) 15); dataLayer = new DataLayer(LAYER_COUNT); ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, - dataLayer, true + dataLayer ); } blockLight[alayer] = dataLayer; @@ -334,7 +317,15 @@ public int[] getHeightMap(HeightMapType type) { @Override public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); @@ -349,6 +340,7 @@ public CompoundTag getEntity(UUID uuid) { @Override public Set getEntities() { + ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { return Collections.emptySet(); @@ -385,7 +377,7 @@ public boolean contains(Object get) { public Iterator iterator() { Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - PaperweightPlatformAdapter.readEntityIntoTag(input, tag); + input.save(tag); return (CompoundTag) adapter.toNative(tag); }).collect(Collectors.toList()); return result.iterator(); @@ -474,7 +466,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz synchronized (super.sectionLocks[getSectionIndex]) { LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; if (createCopy && existingSection != null) { - copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); + copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } if (existingSection == null) { @@ -507,8 +499,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } } } else { - PalettedContainer> biomeData = existingSection.getBiomes(); - setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData); + setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes()); } } } @@ -543,7 +534,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); copy.storeSection(getSectionIndex, copyArr); if (biomes != null && existingSection != null) { - copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); + copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } } @@ -555,8 +546,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz .getBukkitImplAdapter() .getInternalBiomeId( BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, @@ -616,11 +606,11 @@ public synchronized > T call(IChunkSet set, Runnable finaliz sectionLock.writeLock().unlock(); } - PalettedContainer> biomeData = existingSection.getBiomes(); - - if (biomes != null && biomes[setSectionIndex] != null) { - setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData); - } + PalettedContainer> biomeData = setBiomesToPalettedContainer( + biomes, + setSectionIndex, + existingSection.getBiomes() + ); newSection = PaperweightPlatformAdapter.newChunkSection( @@ -705,7 +695,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); + Entity entity = nmsWorld.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -800,7 +790,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); - tileEntity.load(tag); + tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess()); } } } @@ -1076,8 +1066,7 @@ private void fillLightNibble(char[][] light, LightLayer lightLayer, int minSecti ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( lightLayer, sectionPos, - dataLayer, - true + dataLayer ); } synchronized (dataLayer) { @@ -1095,22 +1084,35 @@ private void fillLightNibble(char[][] light, LightLayer lightLayer, int minSecti } } - private void setBiomesToPalettedContainer( - final BiomeType[] biomes, - PalettedContainer> data + private PalettedContainer> setBiomesToPalettedContainer( + final BiomeType[][] biomes, + final int sectionIndex, + final PalettedContainerRO> data ) { - int index = 0; - if (biomes == null) { - return; + PalettedContainer> biomeData; + if (data instanceof PalettedContainer> palettedContainer) { + biomeData = palettedContainer; + } else { + LOGGER.warn( + "Cannot correctly set biomes to world, existing biomes may be lost. Expected class " + + "type {} but got {}", + PalettedContainer.class.getSimpleName(), + data.getClass().getSimpleName() + ); + biomeData = data.recreate(); + } + BiomeType[] sectionBiomes; + if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) { + return biomeData; } - for (int y = 0; y < 4; y++) { + for (int y = 0, index = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { for (int x = 0; x < 4; x++, index++) { - BiomeType biomeType = biomes[index]; + BiomeType biomeType = sectionBiomes[index]; if (biomeType == null) { continue; } - data.set( + biomeData.set( x, y, z, @@ -1122,6 +1124,7 @@ private void setBiomesToPalettedContainer( } } } + return biomeData; } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java similarity index 86% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java index b007ea3b45..c0a7bda523 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.queue.IBlocks; @@ -8,19 +8,23 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import net.minecraft.core.Holder; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.PalettedContainerRO; +import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.Arrays; @@ -33,6 +37,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { + private static final Logger LOGGER = LogManagerCompat.getLogger(); + private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); private final char[][] blocks; @@ -57,7 +63,7 @@ protected void storeTile(BlockEntity blockEntity) { blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))) ); } @@ -76,7 +82,7 @@ public CompoundTag getTile(int x, int y, int z) { protected void storeEntity(Entity entity) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); + entity.save(compoundTag); entities.add((CompoundTag) adapter.toNative(compoundTag)); } @@ -166,11 +172,19 @@ protected void storeSection(int layer, char[] data) { blocks[layer] = data; } - protected void storeBiomes(int layer, PalettedContainer> biomeData) { + protected void storeBiomes(int layer, PalettedContainerRO> biomeData) { if (biomes == null) { biomes = new PalettedContainer[getSectionCount()]; } - biomes[layer] = biomeData; + if (biomeData instanceof PalettedContainer> palettedContainer) { + biomes[layer] = palettedContainer.copy(); + } else { + LOGGER.error( + "Cannot correctly save biomes to history. Expected class type {} but got {}", + PalettedContainer.class.getSimpleName(), + biomeData.getClass().getSimpleName() + ); + } } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java index 9189ca2513..9e226b0883 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightMapChunkUtil.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightMapChunkUtil.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil serverLevel + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel .getChunkSource() - .addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { @@ -286,20 +338,21 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole return; } ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ); - // UNLOADED_CHUNK - Optional optional = ((Either) chunkHolder - .getTickingChunkFuture() - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + LevelChunk levelChunk; if (PaperLib.isPaper()) { // getChunkAtIfLoadedImmediately is paper only - optional = optional.or(() -> Optional.ofNullable(nmsWorld + levelChunk = nmsWorld .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ))); + .getChunkAtIfLoadedImmediately(chunkX, chunkZ); + } else { + levelChunk = ((Optional) ((Either) chunkHolder + .getTickingChunkFuture() // method is not present with new paper chunk system + .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) + .orElse(null); } - if (optional.isEmpty()) { + if (levelChunk == null) { return; } - LevelChunk levelChunk = optional.get(); TaskManager.taskManager().task(() -> { ClientboundLevelChunkWithLightPacket packet; if (PaperLib.isPaper()) { @@ -307,9 +360,8 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole levelChunk, nmsWorld.getChunkSource().getLightEngine(), null, - null, - true, - false // last false is to not bother with x-ray + null + // last false is to not bother with x-ray ); } else { // deprecated on paper - deprecation suppressed @@ -317,8 +369,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole levelChunk, nmsWorld.getChunkSource().getLightEngine(), null, - null, - true + null ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); @@ -424,12 +475,11 @@ public static LevelChunkSection newChunkSection( .getBukkitImplAdapter() .getInternalBiomeId( BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); } - return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); + return new LevelChunkSection(blockStatePalettedContainer, biomes); } catch (final Throwable e) { throw e; } finally { @@ -447,15 +497,14 @@ private static LevelChunkSection newChunkSection( @Nullable PalettedContainer> biomes ) { if (biomes == null) { - return new LevelChunkSection(layer, biomeRegistry); + return new LevelChunkSection(biomeRegistry); } PalettedContainer dataPaletteBlocks = new PalettedContainer<>( Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), - PalettedContainer.Strategy.SECTION_STATES, - null + PalettedContainer.Strategy.SECTION_STATES ); - return new LevelChunkSection(layer, dataPaletteBlocks, biomes); + return new LevelChunkSection(dataPaletteBlocks, biomes); } /** @@ -492,8 +541,7 @@ public static PalettedContainer> getBiomePalettedContainer( PalettedContainer> biomePalettedContainer = new PalettedContainer<>( biomeRegistry, biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), - PalettedContainer.Strategy.SECTION_BIOMES, - null + PalettedContainer.Strategy.SECTION_BIOMES ); final Palette> biomePalette; @@ -571,7 +619,7 @@ public static void clearCounts(final LevelChunkSection section) throws IllegalAc } public static BiomeType adapt(Holder biome, LevelAccessor levelAccessor) { - final Registry biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY); + final Registry biomeRegistry = levelAccessor.registryAccess().registryOrThrow(BIOME); if (biomeRegistry.getKey(biome.value()) == null) { return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN : null; @@ -581,13 +629,11 @@ public static BiomeType adapt(Holder biome, LevelAccessor levelAccessor) static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { try { - // Do the method ourselves to avoid trying to reflect generic method parameters - // similar to removeGameEventListener if (levelChunk.loaded || levelChunk.level.isClientSide()) { BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos()); if (blockEntity != null) { if (!levelChunk.level.isClientSide) { - methodRemoveGameEventListener.invoke(levelChunk, beacon); + methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level); } fieldRemove.set(beacon, true); } @@ -599,30 +645,32 @@ static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { } static List getEntities(LevelChunk chunk) { - return chunk.level.entityManager.getEntities(chunk.getPos()); - } - - public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { - boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread(); - boolean unset = false; - if (isVillager) { - try { - if (fieldOffers.get(entity) != null) { - fieldOffers.set(entity, OFFERS); - unset = true; + ExceptionCollector collector = new ExceptionCollector<>(); + if (PaperLib.isPaper()) { + if (POST_CHUNK_REWRITE) { + try { + //noinspection unchecked + return (List) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e); } - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to set offers field to villager to avoid async catcher.", e); } - } - entity.save(compoundTag); - if (unset) { try { - fieldOffers.set(entity, null); + EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk); + return List.of(entityList.getRawData()); } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to set offers field to null again on villager.", e); + collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e)); + // fall through } } + try { + //noinspection unchecked + return ((PersistentEntitySectionManager) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos()); + } catch (IllegalAccessException e) { + collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e)); + } + collector.throwIfPresent(); + return List.of(); } record FakeIdMapBlock(int size) implements IdMap { diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java similarity index 99% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java index abc8d61505..bc094a916f 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java similarity index 90% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java index c832fc98ac..476978b570 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java @@ -1,14 +1,14 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.queue.IQueueExtent; -import net.minecraft.server.MCUtil; +import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.TicketType; import net.minecraft.util.Unit; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStatus; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -18,7 +18,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter { private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent queue) { super(serverLevel, queue); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java similarity index 88% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java index 735bcc677d..1425088b80 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighterFactory.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighterFactory.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; @@ -7,7 +7,7 @@ import com.fastasyncworldedit.core.queue.IQueueExtent; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; +import org.bukkit.craftbukkit.CraftWorld; import javax.annotation.Nonnull; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java similarity index 98% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java index a890d66a40..11d3c940a6 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/nbt/PaperweightLazyCompoundTag.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/nbt/PaperweightLazyCompoundTag.java @@ -1,4 +1,4 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.LazyCompoundTag; diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java similarity index 69% rename from worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java rename to worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java index 8403d531d0..e21e7eef73 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java @@ -1,17 +1,15 @@ -package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen; +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen; import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightGetBlocks; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.PaperweightGetBlocks; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; @@ -20,14 +18,19 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.minecraft.core.Holder; import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; +import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.thread.ProcessorHandle; +import net.minecraft.util.thread.ProcessorMailbox; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; @@ -37,31 +40,34 @@ import net.minecraft.world.level.biome.FixedBiomeSource; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.UpgradeData; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.WorldGenContext; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.generator.CustomChunkGenerator; +import org.bukkit.Chunk; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.generator.CustomChunkGenerator; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; -import java.io.IOException; import java.lang.reflect.Field; import java.nio.file.Path; import java.util.Collections; @@ -74,6 +80,8 @@ import java.util.function.BooleanSupplier; import java.util.function.Supplier; +import static net.minecraft.core.registries.Registries.BIOME; + public class PaperweightRegen extends Regenerator { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -85,6 +93,7 @@ public class PaperweightRegen extends Regenerator) () -> new ServerLevel( @@ -232,66 +254,70 @@ protected boolean initNewWorld() throws Exception { session, newWorldData, originalServerWorld.dimension(), - originalServerWorld.dimensionTypeRegistration(), + DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow() + .getOrThrow(levelStemResourceKey), new RegenNoOpWorldLoadListener(), - // placeholder. Required for new ChunkProviderServer, but we create and then set it later - newOpts.dimensions().getOrThrow(levelStemResourceKey).generator(), originalServerWorld.isDebug(), seed, ImmutableList.of(), false, + originalServerWorld.getRandomSequences(), environment, generator, biomeProvider ) { - private final Holder singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) : null; + + private final Holder singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) : null; @Override - public void tick(BooleanSupplier shouldKeepTicking) { //no ticking + public void tick(@NotNull BooleanSupplier shouldKeepTicking) { //no ticking } @Override - public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { if (options.hasBiomeType()) { return singleBiome; } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ, - PaperweightRegen.this.chunkGenerator.climateSampler() + return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( + biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() ); } + }).get(); freshWorld.noSave = true; removeWorldFromWorldsMap(); newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name if (paperConfigField != null) { - paperConfigField.set(freshWorld, originalServerWorld.paperConfig); + paperConfigField.set(freshWorld, originalServerWorld.paperConfig()); } - //generator ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); if (originalGenerator instanceof FlatLevelSource flatLevelSource) { FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); - chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat); + chunkGenerator = new FlatLevelSource(generatorSettingFlat); } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - Holder generatorSettingBaseSupplier = - (Holder) generatorSettingBaseSupplierField - .get(originalGenerator); + Holder generatorSettingBaseSupplier = (Holder) + generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator); BiomeSource biomeSource; if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME - .asHolderIdMap() - .byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()))); + biomeSource = new FixedBiomeSource( + DedicatedServer.getServer().registryAccess() + .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( + WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) + ) + ); } else { biomeSource = originalGenerator.getBiomeSource(); } - chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, noiseBasedChunkGenerator.noises, - biomeSource, seed, + chunkGenerator = new NoiseBasedChunkGenerator( + biomeSource, generatorSettingBaseSupplier ); } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.delegate; + chunkGenerator = customChunkGenerator.getDelegate(); } else { LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); return false; @@ -300,22 +326,8 @@ public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); generateConcurrent = generator.isParallelCapable(); } +// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator); - if (hasGeneratedPositions) { - Map>> ringPositions = - (Map>>) ringPositionsField.get( - originalGenerator); - Map>> copy = new Object2ObjectArrayMap<>(ringPositions); - ringPositionsField.set(chunkGenerator, copy); - hasGeneratedPositionsField.setBoolean(chunkGenerator, true); - } - } - - - chunkGenerator.conf = originalServerWorld.spigotConfig; freshChunkProvider = new ServerChunkCache( freshWorld, session, @@ -333,7 +345,7 @@ public Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { ) { // redirect to LevelChunks created in #createChunks @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { + public ChunkAccess getChunk(int x, int z, @NotNull ChunkStatus chunkstatus, boolean create) { ChunkAccess chunkAccess = getChunkAt(x, z); if (chunkAccess == null && create) { chunkAccess = createChunk(getProtoChunkAt(x, z)); @@ -342,11 +354,32 @@ public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean creat } }; + if (seed == originalOpts.seed() && !options.hasBiomeType()) { + // Optimisation for needless ring position calculation when the seed and biome is the same. + ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get( + originalChunkProvider.chunkMap); + boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); + if (hasGeneratedPositions) { + Map>> origPositions = + (Map>>) ringPositionsField.get(state); + Map>> copy = new Object2ObjectArrayMap<>( + origPositions); + ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get( + freshChunkProvider.chunkMap); + ringPositionsField.set(newState, copy); + hasGeneratedPositionsField.setBoolean(newState, true); + } + } + + chunkSourceField.set(freshWorld, freshChunkProvider); //let's start then - structureManager = server.getStructureManager(); - threadedLevelLightEngine = freshChunkProvider.getLightEngine(); + structureTemplateManager = server.getStructureManager(); + threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); + this.worldGenContext = new WorldGenContext(freshWorld, chunkGenerator, structureTemplateManager, + threadedLevelLightEngine + ); return true; } @@ -362,7 +395,7 @@ protected void cleanup() { Fawe.instance().getQueueHandler().sync(() -> { try { freshChunkProvider.close(false); - } catch (IOException e) { + } catch (Exception e) { throw new RuntimeException(e); } }); @@ -385,7 +418,7 @@ protected void cleanup() { @Override protected ProtoChunk createProtoChunk(int x, int z) { return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, - this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null + this.freshWorld.registryAccess().registryOrThrow(BIOME), null ); } @@ -411,7 +444,11 @@ protected List getBlockPopulators() { @Override protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); + TaskManager.taskManager().task(() -> { + final CraftWorld world = freshWorld.getWorld(); + final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); + blockPopulator.populate(world, random, chunk); + }); } @Override @@ -427,14 +464,12 @@ public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { //util @SuppressWarnings("unchecked") private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { @@ -451,11 +486,15 @@ private RegenNoOpWorldLoadListener() { } @Override - public void updateSpawnPos(ChunkPos spawnPos) { + public void updateSpawnPos(@NotNull ChunkPos spawnPos) { } @Override - public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { + public void onStatusChange( + final @NotNull ChunkPos pos, + @org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status + ) { + } @Override @@ -487,15 +526,14 @@ public FastProtoChunk( // avoid warning on paper - // compatibility with spigot - + @SuppressWarnings("unused") // compatibility with spigot public boolean generateFlatBedrock() { return generateFlatBedrock; } // no one will ever see the entities! @Override - public List getEntities() { + public @NotNull List getEntities() { return Collections.emptyList(); } @@ -516,23 +554,41 @@ public int requiredNeighborChunkRadius() { @Override public String name() { - return chunkStatus.getName(); + return chunkStatus.toString(); } @Override public CompletableFuture processChunk(List accessibleChunks) { return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks, - true + worldGenContext, + Runnable::run, + CompletableFuture::completedFuture, + accessibleChunks ); } } + /** + * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid + * work this way. + */ + static class NoOpLightEngine extends ThreadedLevelLightEngine { + + private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { + }, "fawe-no-op"); + private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { + }); + + public NoOpLightEngine(final ServerChunkCache chunkProvider) { + super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); + } + + @Override + public @NotNull CompletableFuture lightChunk(final @NotNull ChunkAccess chunk, final boolean excludeBlocks) { + return CompletableFuture.completedFuture(chunk); + } + + } + } diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index f19c22cb47..f136de3653 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -40,6 +40,7 @@ repositories { name = "Glaremasters" url = uri("https://repo.glaremasters.me/repository/towny/") } + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO Remove when 4.17.0 is released flatDir { dir(File("src/main/resources")) } } @@ -182,7 +183,7 @@ tasks.named("shadowJar") { include(dependency("org.lz4:lz4-java:1.8.0")) } relocate("net.kyori", "com.fastasyncworldedit.core.adventure") { - include(dependency("net.kyori:adventure-nbt:4.16.0")) + include(dependency("net.kyori:adventure-nbt:4.17.0")) } relocate("com.zaxxer", "com.fastasyncworldedit.core.math") { include(dependency("com.zaxxer:SparseBitSet:1.3")) @@ -214,7 +215,7 @@ tasks { versionNumber.set("${project.version}") versionType.set("release") uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar")) - gameVersions.addAll(listOf("1.20.4", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4", "1.18.2")) + gameVersions.addAll(listOf("1.20.6", "1.20.5", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4")) loaders.addAll(listOf("paper", "spigot")) changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" + "FastAsyncWorldEdit/releases/tag/${project.version}") diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java index 607bc75bf2..2a006d1416 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent; import com.fastasyncworldedit.core.util.MathMan; +import com.google.common.collect.Lists; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -24,11 +25,16 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; +import jdk.jfr.Category; +import jdk.jfr.Event; +import jdk.jfr.Label; +import jdk.jfr.Name; import org.apache.logging.log4j.Logger; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.WorldInfo; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -36,6 +42,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -62,7 +69,7 @@ public abstract class Regenerator chunkStatuses = new LinkedHashMap<>(); + protected final LinkedHashMap chunkStatuses = new LinkedHashMap<>(); // TODO (j21): use SequencedMap private final Long2ObjectLinkedOpenHashMap protoChunks = new Long2ObjectLinkedOpenHashMap<>(); private final Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap<>(); protected boolean generateConcurrent = true; @@ -172,51 +179,70 @@ private boolean generate() throws Exception { //TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)? //for now it is working well and fast, if we are bored in the future we could do the research (a lot of it) to reduce the border radius - //generate chunk coords lists with a certain radius - Int2ObjectOpenHashMap chunkCoordsForRadius = new Int2ObjectOpenHashMap<>(); - chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { - if (radius == -1) { //ignore ChunkStatus.EMPTY - return; - } - int border = 10 - radius; //9 = 8 + 1, 8: max border radius used in chunk stages, 1: need 1 extra chunk for chunk - // features to generate at the border of the region - chunkCoordsForRadius.put(radius, getChunkCoordsRegen(region, border)); - }); + // to get the chunks we need to generate in the nth chunk status, we need to know how many chunks + // we need to generate in the n + 1 th chunk status. Summing up the margin solves that + LinkedHashMap chunkCoordsForChunkStatus = new LinkedHashMap<>(); + int borderSum = 1; + // TODO (j21): use SequencedMap#sequencedKeySet().reversed() + final List reversedKeys = Lists.reverse(new ArrayList<>(chunkStatuses.keySet())); + for (final ChunkStatus status : reversedKeys) { + chunkCoordsForChunkStatus.put(status, getChunkCoordsRegen(region, borderSum)); + borderSum += status.requiredNeighborChunkRadius(); + } //create chunks - for (long xz : chunkCoordsForRadius.get(0)) { + // TODO (j21): use SequencedMap#firstEntry().getKey() + for (long xz : chunkCoordsForChunkStatus.get(chunkStatuses.keySet().iterator().next())) { ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz)); protoChunks.put(xz, chunk); } - //generate lists for RegionLimitedWorldAccess, need to be square with odd length (e.g. 17x17), 17 = 1 middle chunk + 8 border chunks * 2 - Int2ObjectOpenHashMap>> worldLimits = new Int2ObjectOpenHashMap<>(); - chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { - if (radius == -1) { //ignore ChunkStatus.EMPTY - return; + // a memory-efficient, lightweight "list" that calculates index -> ChunkAccess + // as needed when accessed + class LazyChunkList extends AbstractList { + private final int size; + private final int minX; + private final int minZ; + private final int sizeSqrt; + + LazyChunkList(int radius, int centerX, int centerZ) { + this.sizeSqrt = radius + 1 + radius; // length of one side + this.size = this.sizeSqrt * this.sizeSqrt; + this.minX = centerX - radius; + this.minZ = centerZ - radius; } - Long2ObjectOpenHashMap> map = new Long2ObjectOpenHashMap<>(); - for (long xz : chunkCoordsForRadius.get(radius)) { - int x = MathMan.unpairIntX(xz); - int z = MathMan.unpairIntY(xz); - List l = new ArrayList<>((radius + 1 + radius) * (radius + 1 + radius)); - for (int zz = z - radius; zz <= z + radius; zz++) { //order is important, first z then x - for (int xx = x - radius; xx <= x + radius; xx++) { - l.add(protoChunks.get(MathMan.pairInt(xx, zz))); - } - } - map.put(xz, l); + @Override + public IChunkAccess get(final int index) { + Objects.checkIndex(index, size); + int absX = (index % sizeSqrt) + minX; + int absZ = (index / sizeSqrt) + minZ; + return protoChunks.get(MathMan.pairInt(absX, absZ)); + } + + @Override + public int size() { + return size; } - worldLimits.put(radius, map); - }); + + } + @Label("Regeneration") + @Category("FAWE") + @Name("fawe.regen") + class RegenerationEvent extends Event { + private String chunkStatus; + private int chunksToProcess; + } //run generation tasks excluding FULL chunk status for (Map.Entry entry : chunkStatuses.entrySet()) { ChunkStatus chunkStatus = entry.getKey(); - int radius = chunkStatus.requiredNeighborChunkRadius0(); + final RegenerationEvent event = new RegenerationEvent(); + event.begin(); + event.chunkStatus = chunkStatus.name(); + int radius = Math.max(1, chunkStatus.requiredNeighborChunkRadius0()); - long[] coords = chunkCoordsForRadius.get(radius); - Long2ObjectOpenHashMap> limitsForRadius = worldLimits.get(radius); + long[] coords = chunkCoordsForChunkStatus.get(chunkStatus); + event.chunksToProcess = coords.length; if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) { SequentialTasks> tasks = getChunkStatusTaskRows(coords, radius); for (ConcurrentTasks para : tasks) { @@ -224,7 +250,8 @@ private boolean generate() throws Exception { for (LongList row : para) { scheduled.add(() -> { for (long xz : row) { - chunkStatus.processChunkSave(xz, limitsForRadius.get(xz)); + chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), + MathMan.unpairIntY(xz))); } }); } @@ -234,7 +261,8 @@ private boolean generate() throws Exception { // every chunk can be processed individually List scheduled = new ArrayList<>(coords.length); for (long xz : coords) { - scheduled.add(() -> chunkStatus.processChunkSave(xz, limitsForRadius.get(xz))); + scheduled.add(() -> chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), + MathMan.unpairIntY(xz)))); } runAndWait(scheduled); } else { // Concurrency.NONE or generateConcurrent == false @@ -242,28 +270,33 @@ private boolean generate() throws Exception { // running regen on the main thread otherwise triggers async-only events on the main thread executor.submit(() -> { for (long xz : coords) { - chunkStatus.processChunkSave(xz, limitsForRadius.get(xz)); + chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), + MathMan.unpairIntY(xz))); } }).get(); // wait until finished this step } + event.commit(); } //convert to proper chunks - for (long xz : chunkCoordsForRadius.get(0)) { + // TODO (j21): use SequencedMap#firstEntry().getValue() + for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { ProtoChunk proto = protoChunks.get(xz); chunks.put(xz, createChunk(proto)); } //final chunkstatus ChunkStatus FULL = getFullChunkStatus(); - for (long xz : chunkCoordsForRadius.get(0)) { //FULL.requiredNeighbourChunkRadius() == 0! + // TODO (j21): use SequencedMap#firstEntry().getValue() + for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { //FULL.requiredNeighbourChunkRadius() == 0! Chunk chunk = chunks.get(xz); FULL.processChunkSave(xz, List.of(chunk)); } //populate List populators = getBlockPopulators(); - for (long xz : chunkCoordsForRadius.get(0)) { + // TODO (j21): use SequencedMap#firstEntry().getValue() + for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { int x = MathMan.unpairIntX(xz); int z = MathMan.unpairIntY(xz); @@ -277,8 +310,10 @@ private boolean generate() throws Exception { }); } - source = new SingleThreadQueueExtent(BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, - BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256); + source = new SingleThreadQueueExtent( + BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, + BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256 + ); source.init(target, initSourceQueueCache(), null); return true; } @@ -503,7 +538,7 @@ private SequentialTasks> getChunkStatusTaskRows( int numlists = Math.min(requiredNeighbors * 2 + 1, maxZ - minZ + 1); Int2ObjectOpenHashMap byZ = new Int2ObjectOpenHashMap<>(); - int expectedListLength = (coordsCount + 1) / (maxZ - minZ); + int expectedListLength = (coordsCount + 1) / (maxZ - minZ + 2); //init lists for (int i = minZ; i <= maxZ; i++) { @@ -581,13 +616,16 @@ void processChunkSave(long xz, List accessibleChunks) { try { processChunk(accessibleChunks).get(); } catch (Exception e) { - LOGGER.error( - "Error while running " + name() + " on chunk " + MathMan.unpairIntX(xz) + "/" + MathMan.unpairIntY(xz), - e - ); + LOGGER.error("Error while running {} on chunk {}/{}", + name(), MathMan.unpairIntX(xz), MathMan.unpairIntY(xz), e); } } + @Override + public String toString() { + return name(); + } + } public static class SequentialTasks extends Tasks { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java index 7b95990843..91ec973bbb 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java @@ -135,7 +135,7 @@ public int[] getCount(int cx, int cz) { @Deprecated(since = "2.0.0") public void cleanup(Chunk chunk) { for (Entity entity : chunk.getEntities()) { - if (entity.getType() == EntityType.DROPPED_ITEM) { + if (entity.getType() == EntityType.ITEM) { entity.remove(); } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java index 4243251276..c650975c33 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java @@ -20,6 +20,7 @@ package com.sk89q.bukkit.util; import com.sk89q.util.ReflectionUtil; +import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -96,12 +97,11 @@ public CommandMap getCommandMap() { return fallbackCommands; } - CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); + CommandMap commandMap = PaperLib.isPaper() ? Bukkit.getCommandMap() : ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); if (commandMap == null) { Bukkit.getServer().getLogger().severe(plugin.getDescription().getName() - + ": Could not retrieve server CommandMap, using fallback instead!"); - fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer()); - Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin); + + ": Could not retrieve server CommandMap"); + throw new IllegalStateException("Failed to retrieve command map, make sure you are running supported server software"); } else { serverCommandMap = commandMap; } diff --git a/worldedit-core/doctools/build.gradle.kts b/worldedit-core/doctools/build.gradle.kts index 6f2123f20f..cf1cf33de7 100644 --- a/worldedit-core/doctools/build.gradle.kts +++ b/worldedit-core/doctools/build.gradle.kts @@ -1,16 +1,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.8.20" + kotlin("jvm") version "1.9.23" application } applyCommonConfiguration() -tasks.withType { - kotlinOptions.jvmTarget = "17" -} - application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter") tasks.named("run") { workingDir = rootProject.projectDir diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java index bc300d5846..e5185e6d8e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java @@ -2,6 +2,7 @@ import com.fastasyncworldedit.core.configuration.file.YamlConfiguration; import com.fastasyncworldedit.core.util.StringMan; +import com.sk89q.util.StringUtil; import com.sk89q.worldedit.internal.util.LogManagerCompat; import org.apache.logging.log4j.Logger; @@ -14,8 +15,10 @@ import java.lang.annotation.Target; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -27,6 +30,9 @@ public class Config { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private final Map removedKeyVals = new HashMap<>(); + private List existingMigrateNodes = null; + public Config() { save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0); } @@ -43,7 +49,8 @@ private T get(String key, Class root) { try { return (T) field.get(instance); } catch (IllegalAccessException e) { - e.printStackTrace(); + LOGGER.error("Failed to get config option: {}", key, e); + return null; } } } @@ -67,6 +74,10 @@ private void set(String key, Object value, Class root) { if (field.getAnnotation(Final.class) != null) { return; } + Migrate migrate = field.getAnnotation(Migrate.class); + if (existingMigrateNodes != null && migrate != null) { + existingMigrateNodes.add(migrate.value()); + } if (field.getType() == String.class && !(value instanceof String)) { value = value + ""; } @@ -74,17 +85,22 @@ private void set(String key, Object value, Class root) { field.set(instance, value); return; } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to set config option: {}", key); } } } - LOGGER.error("Failed to set config option: {}: {} | {} | {}.yml", key, value, instance, root.getSimpleName()); + removedKeyVals.put(key, value); + LOGGER.error( + "Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed.", + key, + value, + instance, + root.getSimpleName() + ); } public boolean load(File file) { - if (!file.exists()) { - return false; - } + existingMigrateNodes = new ArrayList<>(); YamlConfiguration yml = YamlConfiguration.loadConfiguration(file); for (String key : yml.getKeys(true)) { Object value = yml.get(key); @@ -93,6 +109,10 @@ public boolean load(File file) { } set(key, value, getClass()); } + for (String node : existingMigrateNodes) { + removedKeyVals.remove(node); + } + existingMigrateNodes = null; return true; } @@ -113,7 +133,7 @@ public void save(File file) { save(writer, getClass(), instance, 0); writer.close(); } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to save config file: {}", file, e); } } @@ -166,6 +186,19 @@ public void save(File file) { } + /** + * Indicates that a field should be instantiated / created. + * + * @since 2.10.0 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Migrate { + + String value(); + + } + @Ignore // This is not part of the config public static class ConfigBlock { @@ -222,7 +255,6 @@ private void save(PrintWriter writer, Class clazz, final Object instance, int try { String CTRF = System.lineSeparator(); String spacing = StringMan.repeat(" ", indent); - HashMap, Object> instances = new HashMap<>(); for (Field field : clazz.getFields()) { if (field.getAnnotation(Ignore.class) != null) { continue; @@ -239,31 +271,14 @@ private void save(PrintWriter writer, Class clazz, final Object instance, int } if (current == ConfigBlock.class) { current = (Class) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0]; - comment = current.getAnnotation(Comment.class); - if (comment != null) { - for (String commentLine : comment.value()) { - writer.write(spacing + "# " + commentLine + CTRF); - } - } - BlockName blockNames = current.getAnnotation(BlockName.class); - if (blockNames != null) { - writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); - ConfigBlock configBlock = (ConfigBlock) field.get(instance); - if (configBlock == null || configBlock.getInstances().isEmpty()) { - configBlock = new ConfigBlock(); - field.set(instance, configBlock); - for (String blockName : blockNames.value()) { - configBlock.put(blockName, current.getDeclaredConstructor().newInstance()); - } - } - // Save each instance - for (Map.Entry entry : ((Map) configBlock.getRaw()).entrySet()) { - String key = entry.getKey(); - writer.write(spacing + " " + toNodeName(key) + ":" + CTRF); - save(writer, current, entry.getValue(), indent + 4); - } - } + handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current); continue; + } else if (!removedKeyVals.isEmpty()) { + Migrate migrate = field.getAnnotation(Migrate.class); + Object value; + if (migrate != null && (value = removedKeyVals.remove(migrate.value())) != null) { + field.set(instance, value); + } } Create create = field.getAnnotation(Create.class); if (create != null) { @@ -281,7 +296,6 @@ private void save(PrintWriter writer, Class clazz, final Object instance, int writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); if (value == null) { field.set(instance, value = current.getDeclaredConstructor().newInstance()); - instances.put(current, value); } save(writer, current, value, indent + 2); } else { @@ -292,7 +306,42 @@ private void save(PrintWriter writer, Class clazz, final Object instance, int } } } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed to save config file", e); + } + } + + private void handleConfigBlockSave( + PrintWriter writer, + Object instance, + int indent, + Field field, + String spacing, + String CTRF, + Class current + ) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { + Comment comment = current.getAnnotation(Comment.class); + if (comment != null) { + for (String commentLine : comment.value()) { + writer.write(spacing + "# " + commentLine + CTRF); + } + } + BlockName blockNames = current.getAnnotation(BlockName.class); + if (blockNames != null) { + writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); + ConfigBlock configBlock = (ConfigBlock) field.get(instance); + if (configBlock == null || configBlock.getInstances().isEmpty()) { + configBlock = new ConfigBlock<>(); + field.set(instance, configBlock); + for (String blockName : blockNames.value()) { + configBlock.put(blockName, current.getDeclaredConstructor().newInstance()); + } + } + // Save each instance + for (Map.Entry entry : configBlock.getRaw().entrySet()) { + String key = entry.getKey(); + writer.write(spacing + " " + toNodeName(key) + ":" + CTRF); + save(writer, current, entry.getValue(), indent + 4); + } } } @@ -311,7 +360,7 @@ private Field getField(String[] split, Object instance) { return field; } catch (Throwable ignored) { LOGGER.warn( - "Invalid config field: {} for {}", + "Invalid config field: {} for {}. It is possible this is because it has been removed.", StringMan.join(split, "."), toNodeName(instance.getClass().getSimpleName()) ); @@ -379,7 +428,7 @@ private Object getInstance(String[] split, Class root) { return null; } } catch (Throwable e) { - e.printStackTrace(); + LOGGER.error("Failed retrieving instance for config node: {}", StringUtil.joinString(split, "."), e); } return null; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 89f48b697f..63f37fd6b8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -79,6 +79,8 @@ public class Settings extends Config { @Create public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS; @Create + public GENERAL GENERAL; + @Create public ConfigBlock LIMITS; private Settings() { @@ -145,6 +147,14 @@ public FaweLimit getLimit(Actor actor) { limit.MAX_HISTORY, newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE ); + limit.SCHEM_FILE_NUM_LIMIT = Math.max( + limit.SCHEM_FILE_NUM_LIMIT, + newLimit.SCHEM_FILE_NUM_LIMIT != -1 ? newLimit.SCHEM_FILE_NUM_LIMIT : Integer.MAX_VALUE + ); + limit.SCHEM_FILE_SIZE_LIMIT = Math.max( + limit.SCHEM_FILE_SIZE_LIMIT, + newLimit.SCHEM_FILE_SIZE_LIMIT != -1 ? newLimit.SCHEM_FILE_SIZE_LIMIT : Integer.MAX_VALUE + ); limit.MAX_EXPRESSION_MS = Math.max( limit.MAX_EXPRESSION_MS, newLimit.MAX_EXPRESSION_MS != -1 ? newLimit.MAX_EXPRESSION_MS : Integer.MAX_VALUE @@ -353,6 +363,18 @@ public static class LIMITS extends ConfigBlock { " - History on disk or memory will be deleted", }) public int MAX_HISTORY_MB = -1; + @Comment({ + "Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)", + "Set to -1 to disable" + }) + @Migrate("experimental.per-player-file-size-limit") + public int SCHEM_FILE_SIZE_LIMIT = -1; + @Comment({ + "Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)", + "Set to -1 to disable" + }) + @Migrate("experimental.per-player-file-num-limit") + public int SCHEM_FILE_NUM_LIMIT = -1; @Comment("Maximum time in milliseconds //calc can execute") public int MAX_EXPRESSION_MS = 50; @Comment({ @@ -615,18 +637,6 @@ public static class EXPERIMENTAL { }) public boolean ALLOW_TICK_FLUIDS = false; - @Comment({ - "Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)", - "Set to -1 to disable" - }) - public int PER_PLAYER_FILE_SIZE_LIMIT = -1; - - @Comment({ - "Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)", - "Set to -1 to disable" - }) - public int PER_PLAYER_FILE_NUM_LIMIT = -1; - } @Comment({"Web/HTTP connection related settings"}) @@ -744,4 +754,13 @@ public static class LIGHTING { } + public static class GENERAL { + + @Comment({ + "If the player should be relocated/unstuck when a generation command would bury them", + }) + public boolean UNSTUCK_ON_GENERATE = true; + + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java index 00a47178ca..e02e3abc94 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java @@ -15,6 +15,8 @@ public class FaweLimit { public int MAX_BLOCKSTATES = 0; public int MAX_ENTITIES = 0; public int MAX_HISTORY = 0; + public int SCHEM_FILE_SIZE_LIMIT = 0; + public int SCHEM_FILE_NUM_LIMIT = 0; public int MAX_EXPRESSION_MS = 0; public int INVENTORY_MODE = Integer.MAX_VALUE; public int SPEED_REDUCTION = Integer.MAX_VALUE; @@ -111,6 +113,8 @@ public void THROW_MAX_ENTITIES(int amt) { MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE; MAX.MAX_ENTITIES = Integer.MAX_VALUE; MAX.MAX_HISTORY = Integer.MAX_VALUE; + MAX.SCHEM_FILE_NUM_LIMIT = Integer.MAX_VALUE; + MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE; MAX.MAX_EXPRESSION_MS = 50; MAX.FAST_PLACEMENT = true; MAX.CONFIRM_LARGE = true; @@ -237,6 +241,8 @@ public boolean isUnlimited() { && MAX_BLOCKSTATES == Integer.MAX_VALUE && MAX_ENTITIES == Integer.MAX_VALUE && MAX_HISTORY == Integer.MAX_VALUE + && SCHEM_FILE_SIZE_LIMIT == Integer.MAX_VALUE + && SCHEM_FILE_NUM_LIMIT == Integer.MAX_VALUE && INVENTORY_MODE == 0 && SPEED_REDUCTION == 0 && FAST_PLACEMENT @@ -256,6 +262,8 @@ public void set(FaweLimit limit) { MAX_FAILS = limit.MAX_FAILS; MAX_ITERATIONS = limit.MAX_ITERATIONS; MAX_HISTORY = limit.MAX_HISTORY; + SCHEM_FILE_NUM_LIMIT = limit.SCHEM_FILE_NUM_LIMIT; + SCHEM_FILE_SIZE_LIMIT = limit.SCHEM_FILE_SIZE_LIMIT; INVENTORY_MODE = limit.INVENTORY_MODE; SPEED_REDUCTION = limit.SPEED_REDUCTION; FAST_PLACEMENT = limit.FAST_PLACEMENT; @@ -279,6 +287,8 @@ public FaweLimit copy() { limit.MAX_FAILS = MAX_FAILS; limit.MAX_ITERATIONS = MAX_ITERATIONS; limit.MAX_HISTORY = MAX_HISTORY; + limit.SCHEM_FILE_SIZE_LIMIT = SCHEM_FILE_SIZE_LIMIT; + limit.SCHEM_FILE_NUM_LIMIT = SCHEM_FILE_NUM_LIMIT; limit.FAST_PLACEMENT = FAST_PLACEMENT; limit.CONFIRM_LARGE = CONFIRM_LARGE; limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java index 9ce5c24f0a..449e08db3d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEditManifest.java @@ -23,7 +23,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.JarURLConnection; -import java.net.URL; +import java.net.URI; import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -73,8 +73,7 @@ private static Attributes readAttributes() { } try { - URL url = new URL(classPath); - JarURLConnection jarConnection = (JarURLConnection) url.openConnection(); + JarURLConnection jarConnection = (JarURLConnection) URI.create(classPath).toURL().openConnection(); Manifest manifest = jarConnection.getManifest(); return manifest.getMainAttributes(); } catch (IOException e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index dbd698b24f..d3d4569655 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -184,6 +184,9 @@ public int cyl( BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow); + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } actor.print(Caption.of("worldedit.cyl.created", TextComponent.of(affected))); return affected; } @@ -227,6 +230,9 @@ public int cone(Actor actor, LocalSession session, EditSession editSession, BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makeCone(pos, pattern, radiusX, radiusZ, height, !hollow, thickness); + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } actor.printInfo(Caption.of("worldedit.cone.created", TextComponent.of(affected))); return affected; } @@ -293,7 +299,7 @@ public int sphere( } int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); @@ -379,7 +385,7 @@ public int pyramid( worldEdit.checkMaxRadius(size); BlockVector3 pos = session.getPlacementPosition(actor); int affected = editSession.makePyramid(pos, pattern, size, !hollow); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.pyramid.created", TextComponent.of(affected))); @@ -457,7 +463,7 @@ public int generate( hollow, session.getTimeout() ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.generate.created", TextComponent.of(affected))); @@ -741,7 +747,7 @@ public int blobBrush( radius.divide(max), sphericity / 100 ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index a72cba4b37..73cb342747 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -22,6 +22,7 @@ import com.fastasyncworldedit.core.FaweAPI; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Caption; +import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.util.MaskTraverser; @@ -715,6 +716,9 @@ void regenerate( session.setSourceMask(mask); //FAWE end } + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { + ((Player) actor).findFreePosition(); + } if (success) { actor.print(Caption.of("worldedit.regen.regenerated")); } else { @@ -788,7 +792,7 @@ public int deform( String.join(" ", expression), session.getTimeout() ); - if (actor instanceof Player) { + if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) { ((Player) actor).findFreePosition(); } actor.print(Caption.of("worldedit.deform.deformed", TextComponent.of(affected))); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 22d25e5fb7..aa75731450 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -26,6 +26,7 @@ import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder; import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure; import com.fastasyncworldedit.core.util.MainUtil; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Multimap; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -60,15 +61,19 @@ import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.file.FilenameException; import org.apache.logging.log4j.Logger; +import com.sk89q.worldedit.util.paste.EngineHubPaste; +import com.sk89q.worldedit.util.paste.PasteMetadata; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; +import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.exception.StopExecutionException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -79,9 +84,12 @@ import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Base64; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -525,6 +533,42 @@ public void save( .buildAndExec(worldEdit.getExecutorService()); } + @Command( + name = "share", + desc = "Share your clipboard as a schematic online" + ) + @CommandPermissions({ "worldedit.clipboard.share", "worldedit.schematic.share" }) + public void share(Actor actor, LocalSession session, + @Arg(desc = "Schematic name. Defaults to name-millis", def = "") + String schematicName, + @Arg(desc = "Format name.", def = "sponge") + String formatName) throws WorldEditException { + if (true) { + throw new UnsupportedOperationException("This feature is currently not implemented"); + } + if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) { + actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version")); + return; + } + + ClipboardFormat format = ClipboardFormats.findByAlias(formatName); + if (format == null) { + actor.printError(TranslatableComponent.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); + return; + } + + ClipboardHolder holder = session.getClipboard(); + + SchematicShareTask task = new SchematicShareTask(actor, format, holder, schematicName); + AsyncCommandBuilder.wrap(task, actor) + .registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic") + .setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving")) + .setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving")) + .onSuccess("Shared", (url -> actor.printInfo(TextComponent.of(url.toExternalForm() + ".schem").clickEvent(ClickEvent.openUrl(url.toExternalForm() + ".schem"))))) + .onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter()) + .buildAndExec(worldEdit.getExecutorService()); + } + @Command( name = "formats", aliases = {"listformats", "f"}, @@ -689,10 +733,10 @@ public void list( String headerBytesElem = String.format("%.1fkb", totalBytes / 1000.0); - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1) { headerBytesElem += String.format( " / %dkb", - Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT + actor.getLimit().SCHEM_FILE_SIZE_LIMIT ); } @@ -793,14 +837,48 @@ public ClipboardHolder call() throws Exception { } - private static class SchematicSaveTask implements Callable { + private abstract static class SchematicOutputTask implements Callable { + protected final Actor actor; + protected final ClipboardFormat format; + protected final ClipboardHolder holder; - private final Actor actor; - private final ClipboardFormat format; - private final ClipboardHolder holder; + SchematicOutputTask( + Actor actor, + ClipboardFormat format, + ClipboardHolder holder + ) { + this.actor = actor; + this.format = format; + this.holder = holder; + } + + protected void writeToOutputStream(OutputStream outputStream) throws Exception { + Clipboard clipboard = holder.getClipboard(); + Transform transform = holder.getTransform(); + Clipboard target; + // If we have a transform, bake it into the copy + if (transform.isIdentity()) { + target = clipboard; + } else { + FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform); + target = new BlockArrayClipboard(result.getTransformedRegion()); + target.setOrigin(clipboard.getOrigin()); + Operations.completeLegacy(result.copyTo(target)); + } + + try (Closer closer = Closer.create()) { + OutputStream stream = closer.register(outputStream); + BufferedOutputStream bos = closer.register(new BufferedOutputStream(stream)); + ClipboardWriter writer = closer.register(format.getWriter(bos)); + writer.write(target); + } + } + } + + private static class SchematicSaveTask extends SchematicOutputTask { + private File file; private final boolean overwrite; private final File rootDir; - private File file; SchematicSaveTask( Actor actor, @@ -810,11 +888,9 @@ private static class SchematicSaveTask implements Callable { ClipboardHolder holder, boolean overwrite ) { - this.actor = actor; + super(actor, format, holder); this.file = file; this.rootDir = rootDir; - this.format = format; - this.holder = holder; this.overwrite = overwrite; } @@ -826,7 +902,7 @@ public Void call() throws Exception { //FAWE start boolean checkFilesize = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS - && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1; + && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1; double directorysizeKb = 0; String curFilepath = file.getAbsolutePath(); @@ -856,7 +932,7 @@ public Void call() throws Exception { } - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) { if (numFiles == -1) { numFiles = 0; @@ -869,7 +945,7 @@ public Void call() throws Exception { } } } - int limit = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT; + int limit = actor.getLimit().SCHEM_FILE_NUM_LIMIT; if (numFiles >= limit) { TextComponent noSlotsErr = TextComponent.of( //TODO - to be moved into captions/translatablecomponents @@ -920,7 +996,7 @@ public Void call() throws Exception { if (checkFilesize) { double curKb = filesizeKb + directorysizeKb; - int allocatedKb = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT; + int allocatedKb = actor.getLimit().SCHEM_FILE_SIZE_LIMIT; if (overwrite) { curKb -= oldKbOverwritten; @@ -955,11 +1031,11 @@ public Void call() throws Exception { actor.print(kbRemainingNotif); } - if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { + if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) { TextComponent slotsRemainingNotif = TextComponent.of( //TODO - to be moved into captions/translatablecomponents - "You have " + (Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT - numFiles) + "You have " + (actor.getLimit().SCHEM_FILE_NUM_LIMIT - numFiles) + " schematic file slots left.", TextColor.GRAY ); @@ -973,7 +1049,32 @@ public Void call() throws Exception { //FAWE end return null; } + } + + private static class SchematicShareTask extends SchematicOutputTask { + private final String name; + SchematicShareTask(Actor actor, ClipboardFormat format, ClipboardHolder holder, String name) { + super(actor, format, holder); + this.name = name; + } + + @Override + public URL call() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + writeToOutputStream(baos); + } catch (Exception e) { + throw new CommandException(TextComponent.of(e.getMessage()), e, ImmutableList.of()); + } + + EngineHubPaste pasteService = new EngineHubPaste(); + PasteMetadata metadata = new PasteMetadata(); + metadata.author = this.actor.getName(); + metadata.extension = "schem"; + metadata.name = name == null ? actor.getName() + "-" + System.currentTimeMillis() : name; + return pasteService.paste(new String(Base64.getEncoder().encode(baos.toByteArray()), StandardCharsets.UTF_8), metadata).call(); + } } private static class SchematicListTask implements Callable { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java index ceb07a71eb..235cdf761c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/BaseEntity.java @@ -56,6 +56,7 @@ public class BaseEntity implements NbtValued { * @param nbtData NBT data * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)} */ + @SuppressWarnings("this-escape") @Deprecated public BaseEntity(EntityType type, CompoundTag nbtData) { this(type); @@ -87,6 +88,7 @@ public BaseEntity(EntityType type) { * * @param other the object to clone */ + @SuppressWarnings("this-escape") public BaseEntity(BaseEntity other) { checkNotNull(other); this.type = other.getType(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java index 498e5ce9f8..38b79dc34e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/validation/BlockChangeLimiter.java @@ -62,6 +62,7 @@ public int getLimit() { * * @param limit the limit (>= 0) or -1 for no limit */ + @SuppressWarnings("this-escape") // Unlikely anyone is extending this in practice public void setLimit(int limit) { checkArgument(limit >= -1, "limit >= -1 required"); this.limit = limit; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java index 585eaa00e1..47f17781f4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java @@ -19,11 +19,16 @@ package com.sk89q.worldedit.util.io; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.IOException; import java.io.InputStream; public class ForwardSeekableInputStream extends InputStream { + private static final Logger LOGGER = LogManager.getLogger(); + protected InputStream parent; protected long position = 0; @@ -60,7 +65,7 @@ public boolean markSupported() { @Override public int read(byte[] b, int off, int len) throws IOException { - int read = super.read(b, off, len); + int read = parent.read(b, off, len); position += read; return read; } @@ -86,6 +91,7 @@ public long skip(long n) throws IOException { public void seek(long n) throws IOException { long diff = n - position; + LOGGER.error("Seek to {} from {} using {}", n, position, diff); if (diff < 0) { throw new IOException("Can't seek backwards"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java index a5c9fdced0..d133eb54ec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java @@ -357,7 +357,7 @@ public static HttpRequest request(String method, URL url) { */ public static URL url(String url) { try { - return new URL(url); + return URI.create(url).toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } @@ -371,13 +371,7 @@ public static URL url(String url) { */ private static URL reformat(URL existing) { try { - URL url = new URL(existing.toString()); - URI uri = new URI( - url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), - url.getPath(), url.getQuery(), url.getRef() - ); - url = uri.toURL(); - return url; + return existing.toURI().toURL(); } catch (MalformedURLException | URISyntaxException e) { return existing; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java index 680dbed0d4..152dcfea35 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java @@ -83,4 +83,26 @@ public static void pastebin( .buildAndExec(Pasters.getExecutor()); } + + /** + * Submit data to a pastebin service and inform the sender of + * success or failure. + * + * @param supervisor The supervisor instance + * @param sender The sender + * @param content The content + * @param pasteMetadata The paste metadata + * @param successMessage The message builder, given the URL as an arg + */ + public static void pastebin(Supervisor supervisor, final Actor sender, String content, PasteMetadata pasteMetadata, final TranslatableComponent.Builder successMessage) { + Callable task = paster.paste(content, pasteMetadata); + + AsyncCommandBuilder.wrap(task, sender) + .registerWithSupervisor(supervisor, "Submitting content to a pastebin service.") + .setDelayMessage(TranslatableComponent.of("worldedit.pastebin.uploading")) + .onSuccess((String) null, url -> sender.printInfo(successMessage.args(TextComponent.of(url.toString())).build())) + .onFailure("Failed to submit paste", null) + .buildAndExec(Pasters.getExecutor()); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java index f9bf843756..1decfd384a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/EngineHubPaste.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.util.net.HttpRequest; import java.io.IOException; +import java.net.URI; import java.net.URL; import java.util.Map; import java.util.concurrent.Callable; @@ -33,23 +34,38 @@ public class EngineHubPaste implements Paster { private static final Gson GSON = new Gson(); @Override - public Callable paste(String content) { - return new PasteTask(content); + public Callable paste(String content, PasteMetadata metadata) { + return new PasteTask(content, metadata); } private static final class PasteTask implements Callable { private final String content; + private final PasteMetadata metadata; - private PasteTask(String content) { + private PasteTask(String content, PasteMetadata metadata) { this.content = content; + this.metadata = metadata; } @Override public URL call() throws IOException, InterruptedException { URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste"); - SignedPasteResponse response = GSON.fromJson(HttpRequest.get(initialUrl) + HttpRequest requestBuilder = HttpRequest.get(initialUrl); + + requestBuilder.header("x-paste-meta-from", "EngineHub"); + if (metadata.name != null) { + requestBuilder.header("x-paste-meta-name", metadata.name); + } + if (metadata.author != null) { + requestBuilder.header("x-paste-meta-author", metadata.author); + } + if (metadata.extension != null) { + requestBuilder.header("x-paste-meta-extension", metadata.extension); + } + + SignedPasteResponse response = GSON.fromJson(requestBuilder .execute() .expectResponseCode(200) .returnContent() @@ -68,7 +84,7 @@ public URL call() throws IOException, InterruptedException { .execute() .expectResponseCode(200, 204); - return new URL(response.viewUrl); + return URI.create(response.viewUrl).toURL(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java new file mode 100644 index 0000000000..5654e6ae53 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/PasteMetadata.java @@ -0,0 +1,26 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.paste; + +public class PasteMetadata { + public String name; + public String extension; + public String author; +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java index 0b7652b912..ccd5780b0f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/Paster.java @@ -24,6 +24,10 @@ public interface Paster { - Callable paste(String content); + default Callable paste(String content) { + return paste(content, new PasteMetadata()); + } + + Callable paste(String content, PasteMetadata metadata); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java index fcf0bd6614..515d4d53b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/task/FutureForwardingTask.java @@ -82,21 +82,22 @@ public V get(long timeout, TimeUnit unit) throws InterruptedException, Execution return future.get(timeout, unit); } + // TODO: consider deprecating in favor of Future.State? @Override - public State getState() { + public Task.State getState() { if (isCancelled()) { - return State.CANCELLED; + return Task.State.CANCELLED; } else if (isDone()) { try { get(); - return State.SUCCEEDED; + return Task.State.SUCCEEDED; } catch (InterruptedException e) { - return State.CANCELLED; + return Task.State.CANCELLED; } catch (ExecutionException e) { - return State.FAILED; + return Task.State.FAILED; } } else { - return State.RUNNING; + return Task.State.RUNNING; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java index 4d1bde5f8c..7d09d509e2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockCategories.java @@ -33,8 +33,10 @@ public final class BlockCategories { public static final BlockCategory ANCIENT_CITY_REPLACEABLE = get("minecraft:ancient_city_replaceable"); public static final BlockCategory ANIMALS_SPAWNABLE_ON = get("minecraft:animals_spawnable_on"); public static final BlockCategory ANVIL = get("minecraft:anvil"); + public static final BlockCategory ARMADILLO_SPAWNABLE_ON = get("minecraft:armadillo_spawnable_on"); public static final BlockCategory AXOLOTLS_SPAWNABLE_ON = get("minecraft:axolotls_spawnable_on"); public static final BlockCategory AZALEA_GROWS_ON = get("minecraft:azalea_grows_on"); + public static final BlockCategory BADLANDS_TERRACOTTA = get("minecraft:badlands_terracotta"); public static final BlockCategory AZALEA_ROOT_REPLACEABLE = get("minecraft:azalea_root_replaceable"); public static final BlockCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final BlockCategory BAMBOO_PLANTABLE_ON = get("minecraft:bamboo_plantable_on"); @@ -78,6 +80,7 @@ public final class BlockCategories { public static final BlockCategory DIRT = get("minecraft:dirt"); @Deprecated public static final BlockCategory DIRT_LIKE = get("minecraft:dirt_like"); + public static final BlockCategory DOES_NOT_BLOCK_HOPPERS = get("minecraft:does_not_block_hoppers"); public static final BlockCategory DOORS = get("minecraft:doors"); public static final BlockCategory DRAGON_IMMUNE = get("minecraft:dragon_immune"); public static final BlockCategory DRAGON_TRANSPARENT = get("minecraft:dragon_transparent"); @@ -103,6 +106,12 @@ public final class BlockCategories { public static final BlockCategory HOGLIN_REPELLENTS = get("minecraft:hoglin_repellents"); public static final BlockCategory ICE = get("minecraft:ice"); public static final BlockCategory IMPERMEABLE = get("minecraft:impermeable"); + public static final BlockCategory INCORRECT_FOR_DIAMOND_TOOL = get("minecraft:incorrect_for_diamond_tool"); + public static final BlockCategory INCORRECT_FOR_GOLD_TOOL = get("minecraft:incorrect_for_gold_tool"); + public static final BlockCategory INCORRECT_FOR_IRON_TOOL = get("minecraft:incorrect_for_iron_tool"); + public static final BlockCategory INCORRECT_FOR_NETHERITE_TOOL = get("minecraft:incorrect_for_netherite_tool"); + public static final BlockCategory INCORRECT_FOR_STONE_TOOL = get("minecraft:incorrect_for_stone_tool"); + public static final BlockCategory INCORRECT_FOR_WOODEN_TOOL = get("minecraft:incorrect_for_wooden_tool"); public static final BlockCategory INFINIBURN_END = get("minecraft:infiniburn_end"); public static final BlockCategory INFINIBURN_NETHER = get("minecraft:infiniburn_nether"); public static final BlockCategory INFINIBURN_OVERWORLD = get("minecraft:infiniburn_overworld"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 7762ee5320..a2e58a97cd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -60,6 +60,7 @@ public class BlockType implements Keyed, Pattern { private static final Logger LOGGER = LogManagerCompat.getLogger(); private final String id; + @SuppressWarnings("this-escape") private final LazyReference emptyFuzzy = LazyReference.from(() -> new FuzzyBlockState(this)); //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index 4b3204be46..0206cdf925 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -483,6 +483,10 @@ public final class BlockTypes { @Nullable public static final BlockType COPPER_GRATE = init(); @Nullable + public static final BlockType COPPER_ORE = init(); + @Nullable + public static final BlockType COPPER_TRAPDOOR = init(); + @Nullable public static final BlockType CORNFLOWER = init(); @Nullable public static final BlockType CRACKED_DEEPSLATE_BRICKS = init(); @@ -495,6 +499,8 @@ public final class BlockTypes { @Nullable public static final BlockType CRACKED_STONE_BRICKS = init(); @Nullable + public static final BlockType CRAFTER = init(); + @Nullable public static final BlockType CRAFTING_TABLE = init(); @Nullable public static final BlockType CREEPER_HEAD = init(); @@ -685,8 +691,6 @@ public final class BlockTypes { @Nullable public static final BlockType DEEPSLATE_COPPER_ORE = init(); @Nullable - public static final BlockType COPPER_TRAPDOOR = init(); - @Nullable public static final BlockType DEEPSLATE_DIAMOND_ORE = init(); @Nullable public static final BlockType DEEPSLATE_EMERALD_ORE = init(); @@ -747,8 +751,6 @@ public final class BlockTypes { @Nullable public static final BlockType ENDER_CHEST = init(); @Nullable - public static final BlockType EXPOSED_CHISELED_COPPER = init(); - @Nullable public static final BlockType END_GATEWAY = init(); @Nullable public static final BlockType END_PORTAL = init(); @@ -767,6 +769,8 @@ public final class BlockTypes { @Nullable public static final BlockType END_STONE_BRICK_WALL = init(); @Nullable + public static final BlockType EXPOSED_CHISELED_COPPER = init(); + @Nullable public static final BlockType EXPOSED_COPPER = init(); @Nullable public static final BlockType EXPOSED_COPPER_BULB = init(); @@ -836,6 +840,9 @@ public final class BlockTypes { public static final BlockType GRASS = init(); @Nullable public static final BlockType GRASS_BLOCK = init(); + @Deprecated + @Nullable + public static final BlockType GRASS_PATH = init(); @Nullable public static final BlockType GRAVEL = init(); @Nullable @@ -901,6 +908,8 @@ public final class BlockTypes { @Nullable public static final BlockType HAY_BLOCK = init(); @Nullable + public static final BlockType HEAVY_CORE = init(); + @Nullable public static final BlockType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); @Nullable public static final BlockType HONEYCOMB_BLOCK = init(); @@ -925,8 +934,6 @@ public final class BlockTypes { @Nullable public static final BlockType INFESTED_CRACKED_STONE_BRICKS = init(); @Nullable - public static final BlockType CRAFTER = init(); - @Nullable public static final BlockType INFESTED_DEEPSLATE = init(); @Nullable public static final BlockType INFESTED_MOSSY_STONE_BRICKS = init(); @@ -1954,10 +1961,12 @@ public final class BlockTypes { @Nullable public static final BlockType TWISTING_VINES = init(); @Nullable - public static final BlockType VERDANT_FROGLIGHT = init(); - @Nullable public static final BlockType TWISTING_VINES_PLANT = init(); @Nullable + public static final BlockType VAULT = init(); + @Nullable + public static final BlockType VERDANT_FROGLIGHT = init(); + @Nullable public static final BlockType VINE = init(); @Nullable public static final BlockType VOID_AIR = init(); @@ -2026,7 +2035,7 @@ public final class BlockTypes { public static final BlockType WAXED_CUT_COPPER_SLAB = init(); @Nullable public static final BlockType WAXED_CUT_COPPER_STAIRS = init(); - @ Nullable + @Nullable public static final BlockType WAXED_EXPOSED_CHISELED_COPPER = init(); @Nullable public static final BlockType WAXED_EXPOSED_COPPER = init(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java index e1cb08bc8d..9b0d764f18 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java @@ -163,7 +163,7 @@ protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialize throw new InvalidFormatException("Too short block state table"); } currentSerializedValue = blockStatesSerialized[nextSerializedItem++]; - localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits; + localBlockId |= (int) ((currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits); currentSerializedValue >>>= bitsNextLong; remainingBits = 64 - bitsNextLong; } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java index f981593fe2..52044abdf4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java @@ -35,6 +35,8 @@ public final class EntityTypes { @Nullable public static final EntityType AREA_EFFECT_CLOUD = get("minecraft:area_effect_cloud"); @Nullable + public static final EntityType ARMADILLO = get("minecraft:armadillo"); + @Nullable public static final EntityType ARMOR_STAND = get("minecraft:armor_stand"); @Nullable public static final EntityType ARROW = get("minecraft:arrow"); @@ -51,8 +53,12 @@ public final class EntityTypes { @Nullable public static final EntityType BOAT = get("minecraft:boat"); @Nullable + public static final EntityType BOGGED = get("minecraft:bogged"); + @Nullable public static final EntityType BREEZE = get("minecraft:breeze"); @Nullable + public static final EntityType BREEZE_WIND_CHARGE = get("minecraft:breeze_wind_charge"); + @Nullable public static final EntityType CAMEL = get("minecraft:camel"); @Nullable public static final EntityType CAT = get("minecraft:cat"); @@ -171,6 +177,8 @@ public final class EntityTypes { @Nullable public static final EntityType OCELOT = get("minecraft:ocelot"); @Nullable + public static final EntityType OMINOUS_ITEM_SPAWNER = get("minecraft:ominous_item_spawner"); + @Nullable public static final EntityType PAINTING = get("minecraft:painting"); @Nullable public static final EntityType PANDA = get("minecraft:panda"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java index 3b6bdc6b67..466db6fdd4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemCategories.java @@ -29,28 +29,36 @@ public final class ItemCategories { public static final ItemCategory ACACIA_LOGS = get("minecraft:acacia_logs"); public static final ItemCategory ANVIL = get("minecraft:anvil"); + public static final ItemCategory ARMADILLO_FOOD = get("minecraft:armadillo_food"); public static final ItemCategory ARROWS = get("minecraft:arrows"); public static final ItemCategory AXES = get("minecraft:axes"); - public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items"); + public static final ItemCategory AXOLOTL_FOOD = get("minecraft:axolotl_food"); + @Deprecated public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items"); public static final ItemCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final ItemCategory BANNERS = get("minecraft:banners"); public static final ItemCategory BEACON_PAYMENT_ITEMS = get("minecraft:beacon_payment_items"); public static final ItemCategory BEDS = get("minecraft:beds"); + public static final ItemCategory BEE_FOOD = get("minecraft:bee_food"); public static final ItemCategory BIRCH_LOGS = get("minecraft:birch_logs"); public static final ItemCategory BOATS = get("minecraft:boats"); public static final ItemCategory BOOKSHELF_BOOKS = get("minecraft:bookshelf_books"); public static final ItemCategory BREAKS_DECORATED_POTS = get("minecraft:breaks_decorated_pots"); public static final ItemCategory BUTTONS = get("minecraft:buttons"); + public static final ItemCategory CAMEL_FOOD = get("minecraft:camel_food"); public static final ItemCategory CANDLES = get("minecraft:candles"); @Deprecated public static final ItemCategory CARPETS = get("minecraft:carpets"); + public static final ItemCategory CAT_FOOD = get("minecraft:cat_food"); public static final ItemCategory CHERRY_LOGS = get("minecraft:cherry_logs"); + public static final ItemCategory CHEST_ARMOR = get("minecraft:chest_armor"); public static final ItemCategory CHEST_BOATS = get("minecraft:chest_boats"); + public static final ItemCategory CHICKEN_FOOD = get("minecraft:chicken_food"); public static final ItemCategory CLUSTER_MAX_HARVESTABLES = get("minecraft:cluster_max_harvestables"); public static final ItemCategory COAL_ORES = get("minecraft:coal_ores"); public static final ItemCategory COALS = get("minecraft:coals"); public static final ItemCategory COMPASSES = get("minecraft:compasses"); public static final ItemCategory COMPLETES_FIND_TREE_TUTORIAL = get("minecraft:completes_find_tree_tutorial"); public static final ItemCategory COPPER_ORES = get("minecraft:copper_ores"); + public static final ItemCategory COW_FOOD = get("minecraft:cow_food"); public static final ItemCategory CREEPER_DROP_MUSIC_DISCS = get("minecraft:creeper_drop_music_discs"); public static final ItemCategory CREEPER_IGNITERS = get("minecraft:creeper_igniters"); public static final ItemCategory CRIMSON_STEMS = get("minecraft:crimson_stems"); @@ -61,44 +69,82 @@ public final class ItemCategories { public static final ItemCategory DIAMOND_ORES = get("minecraft:diamond_ores"); public static final ItemCategory DIRT = get("minecraft:dirt"); public static final ItemCategory DOORS = get("minecraft:doors"); + public static final ItemCategory DYEABLE = get("minecraft:dyeable"); public static final ItemCategory EMERALD_ORES = get("minecraft:emerald_ores"); + public static final ItemCategory ENCHANTABLE_ARMOR = get("minecraft:enchantable/armor"); + public static final ItemCategory ENCHANTABLE_BOW = get("minecraft:enchantable/bow"); + public static final ItemCategory ENCHANTABLE_CHEST_ARMOR = get("minecraft:enchantable/chest_armor"); + public static final ItemCategory ENCHANTABLE_CROSSBOW = get("minecraft:enchantable/crossbow"); + public static final ItemCategory ENCHANTABLE_DURABILITY = get("minecraft:enchantable/durability"); + public static final ItemCategory ENCHANTABLE_EQUIPPABLE = get("minecraft:enchantable/equippable"); + public static final ItemCategory ENCHANTABLE_FIRE_ASPECT = get("minecraft:enchantable/fire_aspect"); + public static final ItemCategory ENCHANTABLE_FISHING = get("minecraft:enchantable/fishing"); + public static final ItemCategory ENCHANTABLE_FOOT_ARMOR = get("minecraft:enchantable/foot_armor"); + public static final ItemCategory ENCHANTABLE_HEAD_ARMOR = get("minecraft:enchantable/head_armor"); + public static final ItemCategory ENCHANTABLE_LEG_ARMOR = get("minecraft:enchantable/leg_armor"); + public static final ItemCategory ENCHANTABLE_MINING = get("minecraft:enchantable/mining"); + public static final ItemCategory ENCHANTABLE_MINING_LOOT = get("minecraft:enchantable/mining_loot"); + public static final ItemCategory ENCHANTABLE_SHARP_WEAPON = get("minecraft:enchantable/sharp_weapon"); + public static final ItemCategory ENCHANTABLE_SWORD = get("minecraft:enchantable/sword"); + public static final ItemCategory ENCHANTABLE_TRIDENT = get("minecraft:enchantable/trident"); + public static final ItemCategory ENCHANTABLE_VANISHING = get("minecraft:enchantable/vanishing"); + public static final ItemCategory ENCHANTABLE_WEAPON = get("minecraft:enchantable/weapon"); public static final ItemCategory FENCE_GATES = get("minecraft:fence_gates"); public static final ItemCategory FENCES = get("minecraft:fences"); public static final ItemCategory FISHES = get("minecraft:fishes"); public static final ItemCategory FLOWERS = get("minecraft:flowers"); + public static final ItemCategory FOOT_ARMOR = get("minecraft:foot_armor"); public static final ItemCategory FOX_FOOD = get("minecraft:fox_food"); public static final ItemCategory FREEZE_IMMUNE_WEARABLES = get("minecraft:freeze_immune_wearables"); + public static final ItemCategory FROG_FOOD = get("minecraft:frog_food"); @Deprecated public static final ItemCategory FURNACE_MATERIALS = get("minecraft:furnace_materials"); + public static final ItemCategory GOAT_FOOD = get("minecraft:goat_food"); public static final ItemCategory GOLD_ORES = get("minecraft:gold_ores"); public static final ItemCategory HANGING_SIGNS = get("minecraft:hanging_signs"); + public static final ItemCategory HEAD_ARMOR = get("minecraft:head_armor"); public static final ItemCategory HOES = get("minecraft:hoes"); + public static final ItemCategory HOGLIN_FOOD = get("minecraft:hoglin_food"); + public static final ItemCategory HORSE_FOOD = get("minecraft:horse_food"); + public static final ItemCategory HORSE_TEMPT_ITEMS = get("minecraft:horse_tempt_items"); public static final ItemCategory IGNORED_BY_PIGLIN_BABIES = get("minecraft:ignored_by_piglin_babies"); public static final ItemCategory IRON_ORES = get("minecraft:iron_ores"); public static final ItemCategory JUNGLE_LOGS = get("minecraft:jungle_logs"); public static final ItemCategory LAPIS_ORES = get("minecraft:lapis_ores"); public static final ItemCategory LEAVES = get("minecraft:leaves"); public static final ItemCategory LECTERN_BOOKS = get("minecraft:lectern_books"); + public static final ItemCategory LEG_ARMOR = get("minecraft:leg_armor"); + public static final ItemCategory LLAMA_FOOD = get("minecraft:llama_food"); + public static final ItemCategory LLAMA_TEMPT_ITEMS = get("minecraft:llama_tempt_items"); public static final ItemCategory LOGS = get("minecraft:logs"); public static final ItemCategory LOGS_THAT_BURN = get("minecraft:logs_that_burn"); public static final ItemCategory MANGROVE_LOGS = get("minecraft:mangrove_logs"); + public static final ItemCategory MEAT = get("minecraft:meat"); public static final ItemCategory MUSIC_DISCS = get("minecraft:music_discs"); public static final ItemCategory NON_FLAMMABLE_WOOD = get("minecraft:non_flammable_wood"); public static final ItemCategory NOTEBLOCK_TOP_INSTRUMENTS = get("minecraft:noteblock_top_instruments"); public static final ItemCategory OAK_LOGS = get("minecraft:oak_logs"); @Deprecated public static final ItemCategory OCCLUDES_VIBRATION_SIGNALS = get("minecraft:occludes_vibration_signals"); + public static final ItemCategory OCELOT_FOOD = get("minecraft:ocelot_food"); @Deprecated public static final ItemCategory OVERWORLD_NATURAL_LOGS = get("minecraft:overworld_natural_logs"); + public static final ItemCategory PANDA_FOOD = get("minecraft:panda_food"); + public static final ItemCategory PARROT_FOOD = get("minecraft:parrot_food"); + public static final ItemCategory PARROT_POISONOUS_FOOD = get("minecraft:parrot_poisonous_food"); public static final ItemCategory PICKAXES = get("minecraft:pickaxes"); + public static final ItemCategory PIG_FOOD = get("minecraft:pig_food"); public static final ItemCategory PIGLIN_FOOD = get("minecraft:piglin_food"); public static final ItemCategory PIGLIN_LOVED = get("minecraft:piglin_loved"); public static final ItemCategory PIGLIN_REPELLENTS = get("minecraft:piglin_repellents"); public static final ItemCategory PLANKS = get("minecraft:planks"); + public static final ItemCategory RABBIT_FOOD = get("minecraft:rabbit_food"); public static final ItemCategory RAILS = get("minecraft:rails"); public static final ItemCategory REDSTONE_ORES = get("minecraft:redstone_ores"); public static final ItemCategory SAND = get("minecraft:sand"); public static final ItemCategory SAPLINGS = get("minecraft:saplings"); + public static final ItemCategory SHEEP_FOOD = get("minecraft:sheep_food"); public static final ItemCategory SHOVELS = get("minecraft:shovels"); public static final ItemCategory SIGNS = get("minecraft:signs"); + public static final ItemCategory SKULLS = get("minecraft:skulls"); public static final ItemCategory SLABS = get("minecraft:slabs"); public static final ItemCategory SMALL_FLOWERS = get("minecraft:small_flowers"); public static final ItemCategory SMELTS_TO_GLASS = get("minecraft:smelts_to_glass"); @@ -110,18 +156,22 @@ public final class ItemCategories { public static final ItemCategory STONE_BUTTONS = get("minecraft:stone_buttons"); public static final ItemCategory STONE_CRAFTING_MATERIALS = get("minecraft:stone_crafting_materials"); public static final ItemCategory STONE_TOOL_MATERIALS = get("minecraft:stone_tool_materials"); + public static final ItemCategory STRIDER_FOOD = get("minecraft:strider_food"); + public static final ItemCategory STRIDER_TEMPT_ITEMS = get("minecraft:strider_tempt_items"); public static final ItemCategory SWORDS = get("minecraft:swords"); public static final ItemCategory TALL_FLOWERS = get("minecraft:tall_flowers"); public static final ItemCategory TERRACOTTA = get("minecraft:terracotta"); - public static final ItemCategory TOOLS = get("minecraft:tools"); + @Deprecated public static final ItemCategory TOOLS = get("minecraft:tools"); public static final ItemCategory TRAPDOORS = get("minecraft:trapdoors"); public static final ItemCategory TRIM_MATERIALS = get("minecraft:trim_materials"); public static final ItemCategory TRIM_TEMPLATES = get("minecraft:trim_templates"); public static final ItemCategory TRIMMABLE_ARMOR = get("minecraft:trimmable_armor"); + public static final ItemCategory TURTLE_FOOD = get("minecraft:turtle_food"); public static final ItemCategory VILLAGER_PLANTABLE_SEEDS = get("minecraft:villager_plantable_seeds"); public static final ItemCategory WALLS = get("minecraft:walls"); public static final ItemCategory WARPED_STEMS = get("minecraft:warped_stems"); public static final ItemCategory WART_BLOCKS = get("minecraft:wart_blocks"); + public static final ItemCategory WOLF_FOOD = get("minecraft:wolf_food"); public static final ItemCategory WOODEN_BUTTONS = get("minecraft:wooden_buttons"); public static final ItemCategory WOODEN_DOORS = get("minecraft:wooden_doors"); public static final ItemCategory WOODEN_FENCES = get("minecraft:wooden_fences"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java index 16a65c3086..5dc7f92770 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemType.java @@ -42,7 +42,7 @@ public class ItemType implements RegistryItem, Keyed { public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("item type", true); private final String id; - @SuppressWarnings("deprecation") + @SuppressWarnings({"deprecation", "this-escape"}) private transient final LazyReference name = LazyReference.from(() -> { String name = GuavaUtil.firstNonNull( WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) @@ -51,10 +51,12 @@ public class ItemType implements RegistryItem, Keyed { ); return name.isEmpty() ? getId() : name; }); + @SuppressWarnings("this-escape") private transient final LazyReference richName = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) .getRegistries().getItemRegistry().getRichName(this) ); + @SuppressWarnings("this-escape") private transient final LazyReference itemMaterial = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) .getRegistries().getItemRegistry().getMaterial(this) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java index b8064bb94b..f3cd6d0ccc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java @@ -105,6 +105,10 @@ public final class ItemTypes { @Nullable public static final ItemType ARMOR_STAND = init(); @Nullable + public static final ItemType ARMADILLO_SCUTE = init(); + @Nullable + public static final ItemType ARMADILLO_SPAWN_EGG = init(); + @Nullable public static final ItemType ARMS_UP_POTTERY_SHERD = init(); @Nullable public static final ItemType ARROW = init(); @@ -297,6 +301,10 @@ public final class ItemTypes { @Nullable public static final ItemType BLUE_WOOL = init(); @Nullable + public static final ItemType BOGGED_SPAWN_EGG = init(); + @Nullable + public static final ItemType BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = init(); + @Nullable public static final ItemType BONE = init(); @Nullable public static final ItemType BONE_BLOCK = init(); @@ -319,6 +327,8 @@ public final class ItemTypes { @Nullable public static final ItemType BREAD = init(); @Nullable + public static final ItemType BREEZE_ROD = init(); + @Nullable public static final ItemType BREEZE_SPAWN_EGG = init(); @Nullable public static final ItemType BREWER_POTTERY_SHERD = init(); @@ -971,6 +981,12 @@ public final class ItemTypes { @Nullable public static final ItemType FLINT_AND_STEEL = init(); @Nullable + public static final ItemType FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = init(); + @Nullable + public static final ItemType FLOW_BANNER_PATTERN = init(); + @Nullable + public static final ItemType FLOW_POTTERY_SHERD = init(); + @Nullable public static final ItemType FLOWER_BANNER_PATTERN = init(); @Nullable public static final ItemType FLOWER_POT = init(); @@ -1132,6 +1148,10 @@ public final class ItemTypes { @Nullable public static final ItemType GUNPOWDER = init(); @Nullable + public static final ItemType GUSTER_BANNER_PATTERN = init(); + @Nullable + public static final ItemType GUSTER_POTTERY_SHERD = init(); + @Nullable public static final ItemType HANGING_ROOTS = init(); @Nullable public static final ItemType HAY_BLOCK = init(); @@ -1142,6 +1162,8 @@ public final class ItemTypes { @Nullable public static final ItemType HEARTBREAK_POTTERY_SHERD = init(); @Nullable + public static final ItemType HEAVY_CORE = init(); + @Nullable public static final ItemType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); @Nullable public static final ItemType HOGLIN_SPAWN_EGG = init(); @@ -1404,6 +1426,8 @@ public final class ItemTypes { @Nullable public static final ItemType LOOM = init(); @Nullable + public static final ItemType MACE = init(); + @Nullable public static final ItemType MAGENTA_BANNER = init(); @Nullable public static final ItemType MAGENTA_BED = init(); @@ -1668,6 +1692,10 @@ public final class ItemTypes { @Nullable public static final ItemType OCHRE_FROGLIGHT = init(); @Nullable + public static final ItemType OMINOUS_BOTTLE = init(); + @Nullable + public static final ItemType OMINOUS_TRIAL_KEY = init(); + @Nullable public static final ItemType ORANGE_BANNER = init(); @Nullable public static final ItemType ORANGE_BED = init(); @@ -2075,6 +2103,8 @@ public final class ItemTypes { @Nullable public static final ItemType SCAFFOLDING = init(); @Nullable + public static final ItemType SCRAPE_POTTERY_SHERD = init(); + @Nullable public static final ItemType SCULK = init(); @Nullable public static final ItemType SCULK_CATALYST = init(); @@ -2085,6 +2115,7 @@ public final class ItemTypes { @Nullable public static final ItemType SCULK_VEIN = init(); @Nullable + @Deprecated public static final ItemType SCUTE = init(); @Nullable public static final ItemType SEA_LANTERN = init(); @@ -2424,10 +2455,14 @@ public final class ItemTypes { @Nullable public static final ItemType TURTLE_HELMET = init(); @Nullable + public static final ItemType TURTLE_SCUTE = init(); + @Nullable public static final ItemType TURTLE_SPAWN_EGG = init(); @Nullable public static final ItemType TWISTING_VINES = init(); @Nullable + public static final ItemType VAULT = init(); + @Nullable public static final ItemType VERDANT_FROGLIGHT = init(); @Nullable public static final ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = init(); @@ -2614,6 +2649,8 @@ public final class ItemTypes { @Nullable public static final ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = init(); @Nullable + public static final ItemType WIND_CHARGE = init(); + @Nullable public static final ItemType WITCH_SPAWN_EGG = init(); @Nullable public static final ItemType WITHER_ROSE = init(); @@ -2624,6 +2661,8 @@ public final class ItemTypes { @Nullable public static final ItemType WITHER_SPAWN_EGG = init(); @Nullable + public static final ItemType WOLF_ARMOR = init(); + @Nullable public static final ItemType WOLF_SPAWN_EGG = init(); @Nullable public static final ItemType WOODEN_AXE = init(); diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 6498cca7e2..1c3ad6b68e 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { }) api("org.apache.logging.log4j:log4j-api") api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:5.11.0") + testImplementation("org.mockito:mockito-core:5.12.0") } <<<<<<< HEAD