feat(platform): support Purpur 26.3 #1

Merged
dmg merged 1 commits from ticket-408-support-purpur-26-3 into main 2026-10-17 02:25:54 +00:00
4 changed files with 22 additions and 16 deletions

No files matched your search

+3 -3
View File
@@ -1,12 +1,12 @@
# Purpur Harvest
A Purpur 26.2 plugin providing progression-gated, connected crop harvesting and automatic replanting.
A Purpur 26.3 plugin providing progression-gated, connected crop harvesting and automatic replanting.
The approved behavior is specified in the [SoMC OKF wiki](https://git.garvis.dev/dmg/somc-okf/src/branch/main/projects/purpur-harvest/index.md).
## Requirements
- Purpur 26.2 build 2618
- Purpur 26.3 build 2651
- Java 25
## Distribution migration
@@ -19,7 +19,7 @@ New repositories/checkouts/artifacts use `purpur-harvest`; runtime `SpigotHarves
./gradlew clean check jar
```
The plugin JAR is written to `build/libs/`. `check` includes `nativeHarvestTest`: it downloads SHA-256-verified Purpur 2618 under `build/harvest-runtime/`, loads native registry/service providers, and runs real item-stack/drop/replant regressions without starting a listening server. Those tests are not replaced by item mocks or excluded from verification.
The plugin JAR is written to `build/libs/`. `check` includes `nativeHarvestTest`: it downloads SHA-256-verified Purpur 2651 under `build/harvest-runtime/`, loads native registry/service providers, and runs real item-stack/drop/replant regressions without starting a listening server. Those tests are not replaced by item mocks or excluded from verification.
## Commands
+7 -7
View File
@@ -27,9 +27,9 @@ tasks.withType<JavaCompile>().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")
@@ -47,18 +47,18 @@ tasks.test {
// Real ItemStack/drop/replant regressions require the declared runtime's registry and service providers.
val harvestRuntime = layout.buildDirectory.dir("harvest-runtime")
val downloadHarvestRuntime = tasks.register("downloadHarvestRuntime") {
val launcher = harvestRuntime.map { it.file("purpur-26.2-2618.jar") }
val launcher = harvestRuntime.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)
}
@@ -66,7 +66,7 @@ val downloadHarvestRuntime = tasks.register("downloadHarvestRuntime") {
val prepareHarvestRuntime = tasks.register<JavaExec>("prepareHarvestRuntime") {
dependsOn(downloadHarvestRuntime)
javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(25) }
classpath = files(harvestRuntime.map { it.file("purpur-26.2-2618.jar") })
classpath = files(harvestRuntime.map { it.file("purpur-26.3-2651.jar") })
mainClass = "io.papermc.paperclip.Main"
jvmArgs("-Dpaperclip.patchonly=true")
workingDir(harvestRuntime)
@@ -41,12 +41,12 @@ final class NativeRuntime {
try (var resources = new MultiPackResourceManager(PackType.SERVER_DATA, packs.openAllSelected())) {
LayeredRegistryAccess<RegistryLayer> layers = RegistryLayer.createRegistryAccess();
List<Registry.PendingTags<?>> tags = TagLoader.loadTagsForExistingRegistries(resources, layers.getLayer(RegistryLayer.STATIC));
List<HolderLookup.RegistryLookup<?>> 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<HolderLookup.RegistryLookup<?>> 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());
@@ -21,6 +21,7 @@ class PurpurDistributionTest {
assertEquals(version, metadata.get("version"));
assertEquals("SpigotHarvest", metadata.get("name"), "Retain the data directory and persistent namespace");
assertEquals("games.dmg.spigotharvest.SpigotHarvestPlugin", metadata.get("main"));
assertEquals("1.20", metadata.get("api-version"), "Retain the deliberate compatibility floor");
assertTrue(((Map<?, ?>) metadata.get("permissions")).containsKey("spigotharvest.admin"));
assertFalse(jar.stream().anyMatch(entry -> entry.getName().startsWith("org/bukkit/")
|| entry.getName().startsWith("org/purpurmc/") || entry.getName().endsWith("Test.class")));
@@ -41,7 +42,12 @@ class PurpurDistributionTest {
@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.build.2618-stable"));
assertFalse(build.contains("purpur-26.2-2618.jar"));
assertFalse(build.contains("org.spigotmc:spigot-api"));
for (String workflow : new String[] {"ci.yml", "release.yml"}) {
String content = Files.readString(Path.of(".gitea/workflows", workflow));