Support Minecraft 26.1.2 and 26.2

Adds the v26_1_R1 binding, which covers both versions. 26.x servers are
not obfuscated and need Java 25, so the build moves to Gradle 9.5.1 and
paperweight-userdev 2.0.0-beta.21, and the binding compiles against the
26.1.2 dev bundle with a Java 25 toolchain while everything else stays on
Java 21.

On 26.x every world is a dimension inside the main level, so the binding
provides DimensionWorldStorage:
- world folders resolve to <level>/dimensions/<namespace>/<key>
- data packs go to the level's datapacks folder
- Iris data in a pre-26.1 world folder is moved into the dimension
  before Paper imports the world and deletes the old folder
- "main=true" swaps the world in as the level's overworld instead of
  changing level-name

Also:
- INMS compares 1.x and 26.x versions in release order
- data pack formats 101 (26.1.2) and 107 (26.2), declared with
  min_format/max_format from format 82 on
- dimension types get the fields 26.1 added
- the Java safeguard accepts Java 25

Model used: Claude Opus 5.5
This commit is contained in:
piexel committed 2026-10-11 16:48:05 +02:00
1 parent e1514503f6
commit 8a18b6ff8b
17 files changed
+1726 -59

No files matched your search

+18 -13
View File
@@ -50,18 +50,7 @@ class NMSBinding : Plugin<Project> {
it.version.set(config.version)
}
configurations.register(REOBF_CONFIG) { conf ->
conf.isCanBeConsumed = true
conf.isCanBeResolved = false
conf.attributes {
it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
it.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
it.attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
it.attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.OBFUSCATED))
}
conf.outgoing.artifact(tasks.named("remap"))
}
registerReobfConfiguration("remap")
}
val (major, minor) = config.version.parseVersion()
@@ -71,6 +60,20 @@ class NMSBinding : Plugin<Project> {
rootProject.tasks.named("prepareKotlinBuildScriptModel") { it.dependsOn("$path:convert") }
}
private fun Project.registerReobfConfiguration(artifactTask: String) {
val conf = configurations.create(REOBF_CONFIG)
conf.isCanBeConsumed = true
conf.isCanBeResolved = false
conf.attributes {
it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
it.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
it.attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
it.attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.OBFUSCATED))
}
conf.outgoing.artifact(tasks.named(artifactTask))
}
@DisableCachingByDefault
abstract class ConversionTask @Inject constructor(type: Type) : DefaultTask() {
private val pattern: Regex
@@ -163,8 +166,10 @@ class NMSBinding : Plugin<Project> {
private val NEW_LINE = System.lineSeparator()
private val NEW_LINE_BYTES = NEW_LINE.encodeToByteArray()
// "1.21.11-R0.1-SNAPSHOT" -> (21, 11), "26.1.2.build.74-stable" -> (26, 1)
private fun String.parseVersion() = substringBefore('-').split(".").let {
it[1].toInt() to it[2].toInt()
if (it[0] == "1") it[1].toInt() to it[2].toInt()
else it[0].toInt() to it[1].toInt()
}
class Config(