diff --git a/build.gradle.kts b/build.gradle.kts index 44fa18649..c79bb8083 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,7 +34,7 @@ logger.lifecycle(""" ******************************************* """) -var rootVersion by extra("2.8.1") +var rootVersion by extra("2.8.2") var snapshot by extra("SNAPSHOT") var revision: String by extra("") var buildNumber by extra("") diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 4fd69cb65..5d6e7892b 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -241,8 +241,9 @@ fun Project.applyLibrariesConfiguration() { scm { url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") } issueManagement { diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt index 807ee9e8a..8f737e9ce 100644 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ b/buildSrc/src/main/kotlin/PlatformConfig.kt @@ -87,23 +87,27 @@ fun Project.applyPlatformAndCoreConfiguration() { name.set("Alexander Brandes") email.set("contact(at)notmyfault.dev") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } developer { id.set("SirYwell") name.set("Hannes Greule") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } developer { id.set("dordsor21") name.set("dordsor21") organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") } } scm { url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") } issueManagement{ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 13066707a..1cd38a659 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT" griefprevention = "16.18.1" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.99.5.20" +towny = "0.99.6.0" plotsquared = "7.0.0" # Third party @@ -23,9 +23,9 @@ sparsebitset = "1.3" parallelgzip = "1.0.5" adventure = "4.14.0" adventure-bukkit = "4.3.1" -checkerqual = "3.38.0" +checkerqual = "3.39.0" truezip = "6.8.4" -auto-value = "1.10.2" +auto-value = "1.10.4" findbugs = "3.0.2" rhino-runtime = "1.7.14" zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs @@ -46,7 +46,7 @@ text = "3.0.4" piston = "0.5.7" # Tests -mockito = "5.5.0" +mockito = "5.6.0" # Gradle plugins pluginyml = "0.6.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34e8..3fa8f862f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a5..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java index f369b8458..52974fb02 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/PaperweightAdapter.java @@ -38,6 +38,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightPlatformAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.Extent; @@ -288,7 +289,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter getParent() { return parent; @@ -367,7 +363,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); + PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java index f10370b8d..d7c64e800 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java @@ -378,7 +378,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public Iterator iterator() { Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); + PaperweightPlatformAdapter.readEntityIntoTag(input, tag); return (CompoundTag) adapter.toNative(tag); }).collect(Collectors.toList()); return result.iterator(); @@ -445,7 +445,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java index 7825dbc4d..ba75c127f 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java @@ -78,7 +78,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeEntity(Entity entity) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); + PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); entities.add((CompoundTag) adapter.toNative(compoundTag)); } diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java index 0854fc7ad..16dfd7bd8 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightPlatformAdapter.java @@ -34,6 +34,8 @@ import net.minecraft.server.level.TicketType; import net.minecraft.util.BitStorage; import net.minecraft.util.Unit; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.biome.Biome; @@ -90,6 +92,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final Field fieldGameEventDispatcherSections; private static final MethodHandle methodremoveBlockEntityTicker; + private static final Field fieldOffers; + private static final MerchantOffers OFFERS = new MerchantOffers(); + private static final Field fieldRemove; private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -145,6 +150,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); fieldRemove.setAccessible(true); + + fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bU")); + fieldOffers.setAccessible(true); } catch (RuntimeException e) { throw e; } catch (Throwable rethrow) { @@ -492,4 +500,27 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { 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; + } + } 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); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to set offers field to null again on villager.", e); + } + } + } + } 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_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java index 47389b357..1edc3be1d 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_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_18_R2/PaperweightAdapter.java @@ -34,6 +34,7 @@ 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; @@ -270,7 +271,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter getParent() { return parent; @@ -360,7 +356,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); + PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java index d74e60f9d..0c8cccb4c 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_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java @@ -369,7 +369,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public Iterator iterator() { Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); + PaperweightPlatformAdapter.readEntityIntoTag(input, tag); return (CompoundTag) adapter.toNative(tag); }).collect(Collectors.toList()); return result.iterator(); @@ -434,7 +434,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java index 4457286df..be24d8b90 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_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java @@ -80,7 +80,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeEntity(Entity entity) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); + PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); entities.add((CompoundTag) adapter.toNative(compoundTag)); } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java index 1075694b4..06281908d 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java @@ -35,6 +35,8 @@ import net.minecraft.util.ThreadingDetector; import net.minecraft.util.Unit; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.biome.Biome; @@ -98,6 +100,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodremoveTickingBlockEntity; + private static final Field fieldOffers; + private static final MerchantOffers OFFERS = new MerchantOffers(); + private static final Field fieldRemove; private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -158,6 +163,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); fieldRemove.setAccessible(true); + + fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bW")); + fieldOffers.setAccessible(true); } catch (RuntimeException e) { throw e; } catch (Throwable rethrow) { @@ -571,7 +579,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString()); } - @SuppressWarnings("unchecked") static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { try { // Do the method ourselves to avoid trying to reflect generic method parameters @@ -595,6 +602,29 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { 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; + } + } 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); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to set offers field to null again on villager.", e); + } + } + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java index e106c7d56..22c5a07b2 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java @@ -35,6 +35,7 @@ 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_19_R3.PaperweightPlatformAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.Extent; @@ -276,7 +277,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter getParent() { return parent; @@ -321,7 +317,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); + PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java index d6feb4485..7c7446ad2 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java @@ -372,7 +372,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public Iterator iterator() { Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); + PaperweightPlatformAdapter.readEntityIntoTag(input, tag); return (CompoundTag) adapter.toNative(tag); }).collect(Collectors.toList()); return result.iterator(); @@ -437,7 +437,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java index 9cd285fe1..0dd7da167 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java @@ -84,7 +84,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeEntity(Entity entity) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); + PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); entities.add((CompoundTag) adapter.toNative(compoundTag)); } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java index 16210db38..d0ce1c555 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java @@ -38,6 +38,8 @@ import net.minecraft.util.ThreadingDetector; import net.minecraft.util.Unit; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.biome.Biome; @@ -105,6 +107,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodremoveTickingBlockEntity; + private static final Field fieldOffers; + private static final MerchantOffers OFFERS = new MerchantOffers(); + private static final Field fieldRemove; private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -196,6 +201,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bT")); + fieldOffers.setAccessible(true); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { @@ -656,6 +664,29 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { return List.of(); } + 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; + } + } 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); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to set offers field to null again on villager.", e); + } + } + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java index 428176c5f..b40c12b1a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java @@ -27,7 +27,6 @@ import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTConstants; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -35,6 +34,7 @@ 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_20_R1.PaperweightPlatformAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.Extent; @@ -138,6 +138,7 @@ import org.bukkit.generator.ChunkGenerator; import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -159,7 +160,6 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -277,7 +277,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter getParent() { return parent; @@ -321,7 +317,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); Supplier saveTag = () -> { final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); - readEntityIntoTag(mcEntity, minecraftTag); + PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); //add Id for AbstractChangeSet to work final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final Map tags = NbtUtils.getCompoundBinaryTagValues(tag); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java index bc1e0788e..1c741460d 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java @@ -30,7 +30,11 @@ import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import io.papermc.paper.event.block.BeaconDeactivatedEvent; -import net.minecraft.core.*; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.IdMap; +import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; import net.minecraft.nbt.IntTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; @@ -43,7 +47,14 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.*; +import net.minecraft.world.level.chunk.DataLayer; +import net.minecraft.world.level.chunk.HashMapPalette; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.LinearPalette; +import net.minecraft.world.level.chunk.Palette; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.PalettedContainerRO; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.lighting.LevelLightEngine; import org.apache.logging.log4j.Logger; @@ -54,7 +65,17 @@ import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; import org.bukkit.event.entity.CreatureSpawnEvent; import javax.annotation.Nonnull; -import java.util.*; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; @@ -350,7 +371,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public Iterator iterator() { Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - input.save(tag); + PaperweightPlatformAdapter.readEntityIntoTag(input, tag); return (CompoundTag) adapter.toNative(tag); }).collect(Collectors.toList()); return result.iterator(); @@ -415,7 +436,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java index cec07bb38..3b47efcaa 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java @@ -84,7 +84,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { protected void storeEntity(Entity entity) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); - entity.save(compoundTag); + PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); entities.add((CompoundTag) adapter.toNative(compoundTag)); } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 2fe34894d..8083e3fde 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -38,6 +38,9 @@ import net.minecraft.util.ThreadingDetector; import net.minecraft.util.Unit; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.biome.Biome; @@ -108,6 +111,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodremoveTickingBlockEntity; + private static final Field fieldOffers; + private static final MerchantOffers OFFERS = new MerchantOffers(); + /* * This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java * and is only needed to support 1.19.4 versions before *and* after this change. @@ -205,6 +211,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bU")); + fieldOffers.setAccessible(true); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { @@ -674,6 +683,24 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { return List.of(); } + public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { + boolean unset = false; + if (entity instanceof Villager villager && !Fawe.isMainThread()) { + try { + if (fieldOffers.get(entity) == null) { + villager.setOffers(OFFERS); + unset = true; + } + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to set offers field to villager to avoid async catcher.", e); + } + } + entity.save(compoundTag); + if (unset) { + ((Villager) entity).setOffers(null); + } + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts index 540d25cca..041ed296f 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ - the().paperDevBundle("1.20.2-R0.1-20230929.031919-14") + the().paperDevBundle("1.20.2-R0.1-20231008.101509-26") compileOnly(libs.paperlib) } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java index 662212981..5ad9b818a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/InspectBrush.java @@ -74,7 +74,12 @@ public class InspectBrush extends BrushTool { return false; } try { - BlockVector3 target = getTarget(player, rightClick).toBlockPoint(); + Vector3 targetVector = getTarget(player, rightClick); + if (targetVector == null) { + player.print(Caption.of("worldedit.tool.no-block")); + return true; + } + BlockVector3 target = targetVector.toBlockPoint(); final int x = target.getBlockX(); final int y = target.getBlockY(); final int z = target.getBlockZ(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java index 16cc173f8..dec8f46c0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java @@ -12,8 +12,6 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; public class HeightmapProcessor implements IBatchProcessor { @@ -25,7 +23,7 @@ public class HeightmapProcessor implements IBatchProcessor { static { Arrays.fill(COMPLETE, true); - Arrays.fill(AIR_LAYER, (char) 1); + Arrays.fill(AIR_LAYER, (char) BlockTypesCache.ReservedIDs.AIR); } private final int minY; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index 56d2e0882..5579cee89 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -179,14 +179,14 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { for (int z = 0; z < 16; z++) { int zz = z + bz; for (int x = 0; x < 16; x++, index++) { - int xx = bx + x; - int from = blocksGet[index]; - if (from == BlockTypesCache.ReservedIDs.__RESERVED__) { - from = BlockTypesCache.ReservedIDs.AIR; - } - final int combinedFrom = from; final int combinedTo = blocksSet[index]; if (combinedTo != BlockTypesCache.ReservedIDs.__RESERVED__) { + int xx = bx + x; + int from = blocksGet[index]; + if (from == BlockTypesCache.ReservedIDs.__RESERVED__) { + from = BlockTypesCache.ReservedIDs.AIR; + } + final int combinedFrom = from; add(xx, yy, zz, combinedFrom, combinedTo); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java index 7a034d7bd..fa3ef1dc4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java @@ -257,7 +257,8 @@ public class ExtentEntityCopy implements EntityFunction { //FAWE start if (hasRotation) { ListTag orgrot = state.getNbtData().getListTag("Rotation"); - Vector3 orgDirection = new Location(source, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); + // source extent may be null: use non-nullable destination instead since this is just a conversion into a vector. + Vector3 orgDirection = new Location(destination, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); Vector3 newDirection = transform.apply(orgDirection).subtract(transform.apply(Vector3.ZERO)).normalize(); builder.put( "Rotation", @@ -276,7 +277,8 @@ public class ExtentEntityCopy implements EntityFunction { CompoundTagBuilder builder = tag.createBuilder(); ListTag orgrot = state.getNbtData().getListTag("Rotation"); - Vector3 orgDirection = new Location(source, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); + // source extent may be null: use non-nullable destination instead since this is just a conversion into a vector. + Vector3 orgDirection = new Location(destination, 0, 0, 0, orgrot.getFloat(0), orgrot.getFloat(1)).getDirection(); Vector3 newDirection = transform.apply(orgDirection).subtract(transform.apply(Vector3.ZERO)).normalize(); builder.put( "Rotation", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java index 6d11f3b0d..218f54ac0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ForwardExtentCopy.java @@ -500,6 +500,10 @@ public class ForwardExtentCopy implements Operation { } affectedBlocks += blockCopy.getAffected(); + if (copyingBiomes) { + // We know biomes will have happened unless something else has gone wrong. Just calculate it. + affectedBiomeCols += source.fullySupports3DBiomes() ? (getAffected() >> 2) : (region.getWidth() * region.getLength()); + } //FAWE end return null; } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 3c6783886..f1aebbeba 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.5.0") + testImplementation("org.mockito:mockito-core:5.6.0") } <<<<<<< HEAD