From 5949eff7fd34da290c8a02b7cc65a108b731cdc8 Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Fri, 16 Oct 2026 19:50:38 -0400 Subject: [PATCH] fix(base): support Purpur 26.3 --- README.md | 6 ++-- build.gradle.kts | 14 +++++----- .../NativeBaseLabelPacketsTest.java | 2 +- .../games/dmg/spigotbase/NativeRuntime.java | 10 +++---- .../spigotbase/PurpurDistributionTest.java | 28 +++++++++++++++++-- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 41e95f8..0fdadc3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Purpur Base -A Purpur 26.2 plugin providing progression-gated player bases and quality-of-life unlocks. +A Purpur 26.3 plugin providing progression-gated player bases and quality-of-life unlocks. Players begin by breaking Survival-mode grass blocks or dirt. The progression paths provide a persistent base, navigation particles, expanding base bounds, controlled flight, personal teleportation, and visitor teleportation. @@ -10,7 +10,7 @@ The repository and new artifacts are named `purpur-base`. Runtime identity remai ## Requirements -- Purpur 26.2 build 2618 +- Purpur 26.3 build 2651 - Java 25 or newer ## Build @@ -19,7 +19,7 @@ The repository and new artifacts are named `purpur-base`. Runtime identity remai ./gradlew clean check jar ``` -The plugin JAR is written to `build/libs/`. `check` includes native label packet tests against the SHA-256-verified Purpur 2618 runtime. The build downloads/patches that runtime under `build/label-runtime/`, loads its registries, and exercises codecs without starting a listening Minecraft server. +The plugin JAR is written to `build/libs/`. `check` includes native label packet tests against the SHA-256-verified Purpur 2651 runtime. The build downloads/patches that runtime under `build/label-runtime/`, loads its registries, and exercises codecs without starting a listening Minecraft server. ## Player commands diff --git a/build.gradle.kts b/build.gradle.kts index 082c73a..f6e016f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,9 +26,9 @@ tasks.withType().configureEach { } dependencies { - compileOnly("org.purpurmc.purpur:purpur-api:26.2.build.2618-stable") + compileOnly("org.purpurmc.purpur:purpur-api:26.3.build.2651-stable") - testImplementation("org.purpurmc.purpur:purpur-api:26.2.build.2618-stable") + testImplementation("org.purpurmc.purpur:purpur-api:26.3.build.2651-stable") testImplementation(platform("org.junit:junit-bom:5.13.4")) testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.mockito:mockito-core:5.18.0") @@ -46,18 +46,18 @@ tasks.test { // Verify client-only label packets against the declared runtime, without starting a server. val labelRuntime = layout.buildDirectory.dir("label-runtime") val downloadLabelRuntime = tasks.register("downloadLabelRuntime") { - val launcher = labelRuntime.map { it.file("purpur-26.2-2618.jar") } + val launcher = labelRuntime.map { it.file("purpur-26.3-2651.jar") } outputs.file(launcher) doLast { val file = launcher.get().asFile file.parentFile.mkdirs() - val connection = URI("https://api.purpurmc.org/v2/purpur/26.2/2618/download").toURL().openConnection() + val connection = URI("https://api.purpurmc.org/v2/purpur/26.3/2651/download").toURL().openConnection() connection.connectTimeout = 30_000 connection.readTimeout = 120_000 val bytes = connection.getInputStream().use { it.readBytes() } val digest = MessageDigest.getInstance("SHA-256").digest(bytes).joinToString("") { "%02x".format(it) } - check(digest == "4a32d046a118804d89ca74ba89b798c98f6d8d1f310c18077ac573597049de31") { - "Purpur 2618 checksum mismatch" + check(digest == "0677c1febecfbc2e5b0a7f76abd647b70a1f38d3cbdf3dd6a82e401b4262a598") { + "Purpur 2651 checksum mismatch" } file.writeBytes(bytes) } @@ -65,7 +65,7 @@ val downloadLabelRuntime = tasks.register("downloadLabelRuntime") { val prepareLabelRuntime = tasks.register("prepareLabelRuntime") { dependsOn(downloadLabelRuntime) javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(25) } - classpath = files(labelRuntime.map { it.file("purpur-26.2-2618.jar") }) + classpath = files(labelRuntime.map { it.file("purpur-26.3-2651.jar") }) mainClass = "io.papermc.paperclip.Main" jvmArgs("-Dpaperclip.patchonly=true") workingDir(labelRuntime) diff --git a/src/nativeTest/java/games/dmg/spigotbase/NativeBaseLabelPacketsTest.java b/src/nativeTest/java/games/dmg/spigotbase/NativeBaseLabelPacketsTest.java index 5862c72..2d9d919 100644 --- a/src/nativeTest/java/games/dmg/spigotbase/NativeBaseLabelPacketsTest.java +++ b/src/nativeTest/java/games/dmg/spigotbase/NativeBaseLabelPacketsTest.java @@ -45,7 +45,7 @@ class NativeBaseLabelPacketsTest { try { net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket.STREAM_CODEC.encode(buffer, remove); var decoded = net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket.STREAM_CODEC.decode(buffer); - assertEquals(java.util.List.of(42), decoded.getEntityIds()); + assertEquals(java.util.List.of(42), decoded.entityIds()); } finally { buffer.release(); } var player = mock(org.bukkit.craftbukkit.entity.CraftPlayer.class); var handle = mock(net.minecraft.server.level.ServerPlayer.class); diff --git a/src/nativeTest/java/games/dmg/spigotbase/NativeRuntime.java b/src/nativeTest/java/games/dmg/spigotbase/NativeRuntime.java index 653ea0b..d288995 100644 --- a/src/nativeTest/java/games/dmg/spigotbase/NativeRuntime.java +++ b/src/nativeTest/java/games/dmg/spigotbase/NativeRuntime.java @@ -43,12 +43,12 @@ final class NativeRuntime { try (var resources = new MultiPackResourceManager(PackType.SERVER_DATA, packs.openAllSelected())) { LayeredRegistryAccess layers = RegistryLayer.createRegistryAccess(); List> tags = TagLoader.loadTagsForExistingRegistries(resources, layers.getLayer(RegistryLayer.STATIC)); - List> lookups = TagLoader.buildUpdatedLookups(layers.getAccessForLoading(RegistryLayer.WORLDGEN), tags); - RegistryAccess.Frozen worldgen = RegistryDataLoader.load(resources, lookups, - RegistryDataLoader.WORLDGEN_REGISTRIES, Util.backgroundExecutor()).join(); - layers = layers.replaceFrom(RegistryLayer.WORLDGEN, worldgen); + List> lookups = TagLoader.buildUpdatedLookups(layers.getAccessForLoading(RegistryLayer.WORLD), tags); + RegistryAccess.Frozen world = RegistryDataLoader.load(resources, lookups, + RegistryDataLoader.WORLD_REGISTRIES, Util.backgroundExecutor()).join(); + layers = layers.replaceFrom(RegistryLayer.WORLD, world); RegistryAccess.Frozen dimensions = RegistryDataLoader.load(resources, - Stream.concat(lookups.stream(), worldgen.listRegistries()).toList(), + Stream.concat(lookups.stream(), world.listRegistries()).toList(), RegistryDataLoader.DIMENSION_REGISTRIES, Util.backgroundExecutor()).join(); layers = layers.replaceFrom(RegistryLayer.DIMENSIONS, dimensions); Class.forName(org.bukkit.Registry.class.getName()); diff --git a/src/test/java/games/dmg/spigotbase/PurpurDistributionTest.java b/src/test/java/games/dmg/spigotbase/PurpurDistributionTest.java index e12c578..eca69ce 100644 --- a/src/test/java/games/dmg/spigotbase/PurpurDistributionTest.java +++ b/src/test/java/games/dmg/spigotbase/PurpurDistributionTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.io.DataInputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Map; import java.util.jar.JarFile; import org.junit.jupiter.api.Test; @@ -31,16 +32,37 @@ class PurpurDistributionTest { bytecode.readUnsignedShort(); assertEquals(69, bytecode.readUnsignedShort(), "Plugin bytecode must target Java 25"); } - assertFalse(jar.stream().anyMatch(entry -> entry.getName().startsWith("org/bukkit/") - || entry.getName().startsWith("org/purpurmc/") || entry.getName().endsWith("Test.class"))); + List forbiddenPrefixes = List.of( + "com/comphenix/protocol/", + "com/destroystokyo/paper/", + "io/papermc/", + "net/minecraft/", + "org/bukkit/", + "org/purpurmc/", + "org/spigotmc/", + "mockito-extensions/" + ); + assertFalse(jar.stream().anyMatch(entry -> forbiddenPrefixes.stream().anyMatch(entry.getName()::startsWith) + || entry.getName().endsWith("Test.class") + || entry.getName().equals("games/dmg/spigotbase/NativeRuntime.class"))); } } @Test void releaseAndCiAgreeWithThePurpurDistributionNameAndToolchain() throws Exception { String build = Files.readString(Path.of("build.gradle.kts")); - assertTrue(build.contains("purpur-api:26.2.build.2618-stable")); + assertTrue(build.contains("purpur-api:26.3.build.2651-stable")); + assertTrue(build.contains("purpur-26.3-2651.jar")); + assertTrue(build.contains("https://api.purpurmc.org/v2/purpur/26.3/2651/download")); + assertTrue(build.contains("0677c1febecfbc2e5b0a7f76abd647b70a1f38d3cbdf3dd6a82e401b4262a598")); + assertFalse(build.contains("26.2")); + assertFalse(build.contains("2618")); assertFalse(build.contains("org.spigotmc:spigot-api")); + + String readme = Files.readString(Path.of("README.md")); + assertTrue(readme.contains("Purpur 26.3 build 2651")); + assertFalse(readme.contains("Purpur 26.2")); + assertFalse(readme.contains("2618")); for (String workflow : new String[] {"ci.yml", "release.yml"}) { String content = Files.readString(Path.of(".gitea/workflows", workflow)); assertTrue(content.contains("java-version: 25")); -- 2.54.0