From 242b1cc594e8fe72db7d834aca227371c785ebf6 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang <27054324+PierreSchwang@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:40:35 +0200 Subject: [PATCH 1/5] chore: cleanup adapters kind of based on upstream declarative specification for which adapters need to be reobfuscated, directly on the affected adapters. Should also fix some issues with running paperweight on modern toolchains. --- .../buildlogic.adapter-mojmap.gradle.kts | 9 ++++++ .../buildlogic.adapter-reobf.gradle.kts | 24 ++++++++++++++ .../main/kotlin/buildlogic.adapter.gradle.kts | 31 ++++++------------- gradle/libs.versions.toml | 3 ++ .../adapters/adapter-1_21/build.gradle.kts | 3 +- .../adapters/adapter-1_21_11/build.gradle.kts | 2 +- .../adapters/adapter-1_21_4/build.gradle.kts | 2 +- .../adapters/adapter-1_21_5/build.gradle.kts | 2 +- .../adapters/adapter-1_21_6/build.gradle.kts | 2 +- .../adapters/adapter-1_21_9/build.gradle.kts | 2 +- .../adapters/adapter-26.1/build.gradle.kts | 2 +- .../adapters/adapter-26.2/build.gradle.kts | 2 +- 12 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts create mode 100644 build-logic/src/main/kotlin/buildlogic.adapter-reobf.gradle.kts diff --git a/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts new file mode 100644 index 0000000000..190de14e9a --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.adapter-mojmap.gradle.kts @@ -0,0 +1,9 @@ +import io.papermc.paperweight.userdev.ReobfArtifactConfiguration + +plugins { + id("buildlogic.adapter") +} + +paperweight { + reobfArtifactConfiguration = ReobfArtifactConfiguration.MOJANG_PRODUCTION +} diff --git a/build-logic/src/main/kotlin/buildlogic.adapter-reobf.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter-reobf.gradle.kts new file mode 100644 index 0000000000..9adb364ea7 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.adapter-reobf.gradle.kts @@ -0,0 +1,24 @@ +import io.papermc.paperweight.userdev.ReobfArtifactConfiguration + +plugins { + id("buildlogic.adapter") +} + +paperweight { + reobfArtifactConfiguration = ReobfArtifactConfiguration.REOBF_PRODUCTION + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(21) + } +} + +tasks.named("assemble") { + dependsOn("reobfJar") +} + +tasks + .withType() + .matching { it.name == "compileJava" || it.name == "compileTestJava" } + .configureEach { + // We use Java 21 for most of the pre-existing adapters. + options.release.set(21) + } diff --git a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts index 6e1f0ee391..7a4e6aecdd 100644 --- a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts @@ -8,28 +8,18 @@ plugins { id("io.papermc.paperweight.userdev") } -val requiresReobfJar = project.name.startsWith("adapter-1_") - -paperweight { - injectPaperRepository = false - reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION -} - repositories { - maven { - name = "PaperMC" - url = uri("https://repo.papermc.io/repository/maven-public/") - } maven { name = "EngineHub Repository" url = uri("https://maven.enginehub.org/repo/") - content { - excludeModule("net.fabricmc", "yarn") - } } maven { - name = "IntellectualSites" - url = uri("https://repo.intellectualsites.dev/repository/maven-all/") + name = "PaperMC" + url = uri("https://repo.papermc.io/repository/maven-public/") + } + maven { + name = "FabricMC (Yarn)" + url = uri("https://maven.fabricmc.net/#yarn-only") } mavenCentral() afterEvaluate { @@ -45,6 +35,9 @@ dependencies { version { strictly(stringyLibs.getVersion("adventure").strictVersion) } because("Ensure a consistent version of adventure is used.") } + "remapper"("net.fabricmc:tiny-remapper:[${stringyLibs.getVersion("minimumTinyRemapper")},)") { + because("Need remapper to support Java 21") + } } } @@ -53,12 +46,6 @@ java { disableAutoTargetJvm() } -tasks.named("assemble") { - if (requiresReobfJar) { - dependsOn("reobfJar") - } -} - tasks.named("javadoc") { enabled = false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db2b16a38f..9c5c0796d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,6 +7,9 @@ log4j = "2.17.1" gson = "2.11.0" snakeyaml = "2.2" +# Minimum versions we apply to make dependencies support newer Java +minimumTinyRemapper = "0.8.11" + # Plugins dummypermscompat = "1.10" worldguard-bukkit = "7.0.17" diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 0dd0b514e3..f6523c14ea 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -1,8 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") - + id("buildlogic.adapter-reobf") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-1_21_11/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_11/build.gradle.kts index 5a8208563c..1f89c3de9e 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_11/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_11/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-reobf") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts index 8d263bc13f..c4de0056e4 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-reobf") } diff --git a/worldedit-bukkit/adapters/adapter-1_21_5/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_5/build.gradle.kts index 70727ae1c9..d7a3946039 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_5/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_5/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-reobf") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-1_21_6/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_6/build.gradle.kts index 924b3c520a..18a332c3d3 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_6/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_6/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-reobf") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-1_21_9/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_9/build.gradle.kts index 2752f38935..951353afe4 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_9/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_9/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-reobf") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-26.1/build.gradle.kts b/worldedit-bukkit/adapters/adapter-26.1/build.gradle.kts index be3d1a6918..92a5117889 100644 --- a/worldedit-bukkit/adapters/adapter-26.1/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-26.1/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-mojmap") } dependencies { diff --git a/worldedit-bukkit/adapters/adapter-26.2/build.gradle.kts b/worldedit-bukkit/adapters/adapter-26.2/build.gradle.kts index 22f17fa769..948bbd1100 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-26.2/build.gradle.kts @@ -1,7 +1,7 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - id("buildlogic.adapter") + id("buildlogic.adapter-mojmap") } // workaround LeafPile providing wrong snakeyaml version From 1d28df96c377e420a09fcc5757c1aa02b358abfc Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang <27054324+PierreSchwang@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:40:41 +0200 Subject: [PATCH 2/5] fix: include adapters for MC 26+ in spigot again Starting with MC 26(.1), Spigot uses Mojang mappings for the server JAR. The configuration of the bukkit module did not include the unobfuscated adapters for the newer versions due to not differentiating between reobfuscation requirements between platforms. --- worldedit-bukkit/build.gradle.kts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 25dd26f9d4..df249f5189 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -47,7 +47,7 @@ val localImplementation = configurations.create("localImplementation") { configurations["compileOnly"].extendsFrom(localImplementation) configurations["testImplementation"].extendsFrom(localImplementation) -val adapters = configurations.create("adapters") { +val adaptersMojmap = configurations.create("adapters") { description = "Adapters to include in the JAR (Mojmap)" isCanBeConsumed = false isCanBeResolved = true @@ -67,6 +67,17 @@ val adaptersReobf = configurations.create("adaptersReobf") { } } +val adaptersGlobalMojmap = configurations.create("adaptersGlobalMojmap") { + extendsFrom(adaptersMojmap) + isCanBeConsumed = false + isCanBeResolved = true + shouldResolveConsistentlyWith(configurations["runtimeClasspath"]) + description = "Adapters which are included in Spigot + Paper JARs without being remapped (26+)" + attributes { + attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.NONE)) + } +} + allprojects { configurations.configureEach { resolutionStrategy { @@ -103,9 +114,18 @@ dependencies { implementation(libs.fastutil) project.project(":worldedit-bukkit:adapters").subprojects.forEach { - "adapters"(project(it.path)) + // If the adapter module name starts with `adapter-1`, the adapter itself must be reobfuscated for spigot + // Otherwise, if the adapter starts with e.g. `adapter-26` the adapter does not need any reobfuscation as Spigot + // supports mojang-mapped code starting with MC 26 + // Paper supports Mojang-Mapped adapters for the whole range of supported adapter versions if (it.name.startsWith("adapter-1_")) { + // use adapters as is for Paper + "adapters"(project(it.path)) + // reobfuscate adapters for spigot "adaptersReobf"(project(it.path)) + } else { + // don't reobfuscate for Paper or Spigot + "adaptersGlobalMojmap"(project(it.path)) } } compileOnly(libs.worldguard) { @@ -152,7 +172,8 @@ tasks.register("reobfShadowJar") { archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}") configurations = listOf( project.configurations.runtimeClasspath.get(), // as is done by shadow for the default shadowJar - adaptersReobf + adaptersReobf, + adaptersGlobalMojmap ) relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") @@ -186,7 +207,7 @@ tasks.register("reobfShadowJar") { tasks.named("shadowJar") { archiveFileName.set("${rootProject.name}-Paper-${project.version}.${archiveExtension.getOrElse("jar")}") - configurations.add(adapters) + configurations.addAll(adaptersMojmap, adaptersGlobalMojmap) manifest { attributes( "paperweight-mappings-namespace" to "mojang", From 4005df82b4a1c8f8983a2c17a47c170ae7bdda27 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang <27054324+PierreSchwang@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:40:43 +0200 Subject: [PATCH 3/5] fix: spigot compatibility for 26.2 - Refraction is not required anymore. - Conversion between NMS and CB BlockStates requires reflection / MH invocations on Spigot (Paper method does not exist on Spigot, and Spigot method is not available in Paper and can't be called directly therefor) --- .../fawe/v26_2/PaperweightFaweAdapter.java | 8 ++- .../PaperweightFaweWorldNativeAccess.java | 14 ++++- .../v26_2/PaperweightPlatformAdapter.java | 51 +++++++------------ .../impl/fawe/v26_2/PlatformCompat.java | 50 ++++++++++++++++++ .../impl/v26_2/PaperweightBlockMaterial.java | 3 +- 5 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java index e5716ab6d7..c7e3de0857 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java @@ -251,8 +251,12 @@ private synchronized boolean init() { @Override public Collection getRegisteredDefaultBlockStates() { ArrayList states = new ArrayList<>(); - for (final Block block : BuiltInRegistries.BLOCK) { - states.add(block.defaultBlockState().asBlockData().getAsString()); + try { + for (final Block block : BuiltInRegistries.BLOCK) { + states.add(PlatformCompat.fromData(block.defaultBlockState()).getAsString()); + } + } catch (Throwable e) { + LOGGER.error("Failed to initialize block state", e); } return states; } diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java index 29a5711dcc..ebf7fd90c6 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java @@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; @@ -21,6 +22,7 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; import net.minecraft.world.level.storage.ValueInput; +import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; @@ -39,6 +41,8 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess { + private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static final int UPDATE = 1; private static final int NOTIFY = 2; private static final Direction[] NEIGHBOUR_ORDER = { @@ -207,9 +211,15 @@ public void updateNeighbors( if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { CraftWorld craftWorld = level.getWorld(); if (craftWorld != null) { + CraftBlockData cbd; + try { + cbd = PlatformCompat.fromData(newState); + } catch (Throwable e) { + LOGGER.error("Failed to update neighbors: Failed to convert BlockState to CraftBlockData", e); + return; + } BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), - newState.asBlockData() + craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), cbd ); level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightPlatformAdapter.java index ec306e9831..1170b15bb0 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightPlatformAdapter.java @@ -15,7 +15,6 @@ import com.mojang.serialization.DataResult; 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.v26_2.PaperweightBlockMaterial; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.world.biome.BiomeType; @@ -112,31 +111,28 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { - fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "b")); + fieldData = PalettedContainer.class.getDeclaredField("data"); fieldData.setAccessible(true); Class dataClazz = fieldData.getType(); dataConstructor = dataClazz.getDeclaredConstructors()[0]; dataConstructor.setAccessible(true); - fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b")); + fieldStorage = dataClazz.getDeclaredField("storage"); fieldStorage.setAccessible(true); - fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c")); + fieldPalette = dataClazz.getDeclaredField("palette"); fieldPalette.setAccessible(true); - //noinspection JavaLangInvokeHandleSignature - method is obfuscated + //noinspection JavaLangInvokeHandleSignature - signature differs between Paper and Spigot palettedContainerUnpackSpigot = PaperSupport.isPaper() ? null : lookup.findStatic( - PalettedContainer.class, - "a", // unpack - MethodType.methodType(DataResult.class, Strategy.class, PalettedContainerRO.PackedData.class) + PalettedContainer.class, + "unpack", + MethodType.methodType(DataResult.class, Strategy.class, PalettedContainerRO.PackedData.class) ); - fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName( - "tickingFluidCount", - "g" - )); + fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField("tickingFluidCount"); fieldTickingFluidCount.setAccessible(true); - fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f")); + fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField("tickingBlockCount"); fieldTickingBlockCount.setAccessible(true); Field tmpFieldBiomes; try { @@ -148,21 +144,16 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { fieldBiomes = tmpFieldBiomes; fieldBiomes.setAccessible(true); - Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod( - Refraction.pickName( - "getVisibleChunkIfPresent", - "b" - ), long.class - ); + Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod("getVisibleChunkIfPresent", long.class); getVisibleChunkIfPresent.setAccessible(true); methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent); if (!PaperSupport.isPaper()) { - fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "d")); + fieldThreadingDetector = PalettedContainer.class.getDeclaredField("threadingDetector"); fieldThreadingDetector.setAccessible(true); - fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c")); + fieldLock = ThreadingDetector.class.getDeclaredField("lock"); fieldLock.setAccessible(true); - SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M")); + SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager"); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true); } else { // in paper, the used methods are synchronized properly @@ -171,29 +162,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( - Refraction.pickName("removeGameEventListener", "a"), + "removeGameEventListener", BlockEntity.class, ServerLevel.class ); removeGameEventListener.setAccessible(true); methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener); - Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod( - Refraction.pickName( - "removeBlockEntityTicker", - "k" - ), BlockPos.class - ); + Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod("removeBlockEntityTicker", BlockPos.class); removeBlockEntityTicker.setAccessible(true); methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker); - fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); + fieldRemove = BlockEntity.class.getDeclaredField("remove"); fieldRemove.setAccessible(true); - Method palettedContainerGet = PalettedContainer.class.getDeclaredMethod( - Refraction.pickName("get", "a"), - int.class - ); + Method palettedContainerGet = PalettedContainer.class.getDeclaredMethod("get", int.class); palettedContainerGet.setAccessible(true); PALETTED_CONTAINER_GET = lookup.unreflect(palettedContainerGet); } catch (RuntimeException | Error e) { diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java new file mode 100644 index 0000000000..75b2318b12 --- /dev/null +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java @@ -0,0 +1,50 @@ +package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2; + +import com.fastasyncworldedit.bukkit.util.PaperSupport; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import net.minecraft.world.level.block.state.BlockState; +import org.apache.logging.log4j.Logger; +import org.bukkit.craftbukkit.block.data.CraftBlockData; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public final class PlatformCompat { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private static MethodHandle SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA; + + static { + if (!PaperSupport.isPaper()) { + try { + //noinspection JavaLangInvokeHandleSignature (not available on Paper) + SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA = MethodHandles.lookup().findStatic( + CraftBlockData.class, + "fromData", + MethodType.methodType(CraftBlockData.class, net.minecraft.world.level.block.state.BlockState.class) + ); + } catch (NoSuchMethodException | IllegalAccessException e) { + LOGGER.error("Failed to lookup CraftBlockData#fromData(BlockState)", e); + } + } + } + + public static CraftBlockData fromData(BlockState state) throws Throwable { + if (SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA == null) { + return state.asBlockData(); + } + return (CraftBlockData) SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA.invokeExact(state); + } + + public static CraftBlockData fromDataUnsafe(BlockState state) { + try { + return fromData(state); + } catch (Throwable e) { + LOGGER.error("Unsafe call to #fromData", e); + } + return null; // this will most likely fail somewhere along the call (NPE) + } + +} diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java index 7b4c8bbcd8..8267fb5ece 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java @@ -22,6 +22,7 @@ import com.fastasyncworldedit.bukkit.adapter.BukkitBlockMaterial; import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2.PaperweightGetBlocks; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2.PlatformCompat; import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; @@ -38,7 +39,7 @@ public PaperweightBlockMaterial(Block block) { } public PaperweightBlockMaterial(Block block, BlockState blockState) { - super(block, blockState, blockState.asBlockData()); + super(block, blockState, PlatformCompat.fromDataUnsafe(blockState)); } @Override From 2f87bdde36bf2e78a6e60de7fee8f04599332180 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang <27054324+PierreSchwang@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:50:56 +0200 Subject: [PATCH 4/5] fix(build): don't purge Yarn repository --- build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts index 7a4e6aecdd..adf84b33f7 100644 --- a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts @@ -12,6 +12,9 @@ repositories { maven { name = "EngineHub Repository" url = uri("https://maven.enginehub.org/repo/") + content { + excludeModule("net.fabricmc", "yarn") + } } maven { name = "PaperMC" @@ -22,9 +25,6 @@ repositories { url = uri("https://maven.fabricmc.net/#yarn-only") } mavenCentral() - afterEvaluate { - killNonEngineHubRepositories() - } } dependencies { From 571252a1c4b72e1b514bcd6cc499d135f0f76289 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang <27054324+PierreSchwang@users.noreply.github.com> Date: Mon, 31 Aug 2026 11:57:18 +0200 Subject: [PATCH 5/5] chore: address review comments --- .../fawe/v26_2/PaperweightFaweAdapter.java | 8 ++--- .../PaperweightFaweWorldNativeAccess.java | 14 ++------- .../impl/fawe/v26_2/PlatformCompat.java | 30 +++++++++++-------- .../impl/v26_2/PaperweightBlockMaterial.java | 2 +- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java index c7e3de0857..f2acb58d6b 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java @@ -251,12 +251,8 @@ private synchronized boolean init() { @Override public Collection getRegisteredDefaultBlockStates() { ArrayList states = new ArrayList<>(); - try { - for (final Block block : BuiltInRegistries.BLOCK) { - states.add(PlatformCompat.fromData(block.defaultBlockState()).getAsString()); - } - } catch (Throwable e) { - LOGGER.error("Failed to initialize block state", e); + for (final Block block : BuiltInRegistries.BLOCK) { + states.add(PlatformCompat.fromData(block.defaultBlockState()).getAsString()); } return states; } diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java index ebf7fd90c6..7b04a7f3c4 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java @@ -6,7 +6,6 @@ import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; @@ -22,7 +21,6 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; import net.minecraft.world.level.storage.ValueInput; -import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; @@ -41,8 +39,6 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess { - private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static final int UPDATE = 1; private static final int NOTIFY = 2; private static final Direction[] NEIGHBOUR_ORDER = { @@ -211,15 +207,9 @@ public void updateNeighbors( if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { CraftWorld craftWorld = level.getWorld(); if (craftWorld != null) { - CraftBlockData cbd; - try { - cbd = PlatformCompat.fromData(newState); - } catch (Throwable e) { - LOGGER.error("Failed to update neighbors: Failed to convert BlockState to CraftBlockData", e); - return; - } BlockPhysicsEvent event = new BlockPhysicsEvent( - craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), cbd + craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), + PlatformCompat.fromData(newState) ); level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java index 75b2318b12..113c7af3b8 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PlatformCompat.java @@ -14,37 +14,43 @@ public final class PlatformCompat { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private static MethodHandle SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA; + private static final MethodHandle SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA; static { + MethodHandle tmpSpigotCraftBlockDataFromData = null; if (!PaperSupport.isPaper()) { try { //noinspection JavaLangInvokeHandleSignature (not available on Paper) - SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA = MethodHandles.lookup().findStatic( + tmpSpigotCraftBlockDataFromData = MethodHandles.lookup().findStatic( CraftBlockData.class, "fromData", - MethodType.methodType(CraftBlockData.class, net.minecraft.world.level.block.state.BlockState.class) + MethodType.methodType(CraftBlockData.class, BlockState.class) ); } catch (NoSuchMethodException | IllegalAccessException e) { LOGGER.error("Failed to lookup CraftBlockData#fromData(BlockState)", e); } } + SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA = tmpSpigotCraftBlockDataFromData; } - public static CraftBlockData fromData(BlockState state) throws Throwable { + /** + * Adapts a {@link BlockState} to a {@link CraftBlockData} using platform-specific methods. + * On Paper {@code BlockState#asBlockData()} is used, on Spigot {@code CraftBlockData#fromData(BlockState)} is used. + *

+ * Uses reflection on Spigot, as Paper dropped the Spigot method (-> Can't be directly called). + * + * @param state the {@link BlockState} to adapt. + * @return the {@link CraftBlockData} + */ + public static CraftBlockData fromData(BlockState state) { if (SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA == null) { return state.asBlockData(); } - return (CraftBlockData) SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA.invokeExact(state); - } - - public static CraftBlockData fromDataUnsafe(BlockState state) { try { - return fromData(state); - } catch (Throwable e) { - LOGGER.error("Unsafe call to #fromData", e); + return (CraftBlockData) SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA.invokeExact(state); + } catch (Throwable throwable) { + throw new RuntimeException("Caught unexpected Exception while converting BlockState to CraftBlockData", throwable); } - return null; // this will most likely fail somewhere along the call (NPE) } } diff --git a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java index 8267fb5ece..7ec90111d4 100644 --- a/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java @@ -39,7 +39,7 @@ public PaperweightBlockMaterial(Block block) { } public PaperweightBlockMaterial(Block block, BlockState blockState) { - super(block, blockState, PlatformCompat.fromDataUnsafe(blockState)); + super(block, blockState, PlatformCompat.fromData(blockState)); } @Override