import art.arcane.volmit.packaging.PackedJar import art.arcane.volmit.packaging.PackagingMode import art.arcane.volmit.packaging.NativeDevelopmentTargets import io.papermc.paperweight.userdev.PaperweightUser import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension import io.papermc.paperweight.userdev.PaperweightUserExtension import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.Provider import org.gradle.jvm.toolchain.JavaLauncher import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.api.file.CopySpec import org.gradle.api.file.DeleteSpec import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.FileTree import org.gradle.api.plugins.JavaPlugin import org.gradle.api.initialization.IncludedBuild import org.gradle.api.tasks.Copy import org.gradle.api.tasks.compile.JavaCompile import org.gradle.jvm.tasks.Jar import org.gradle.jvm.toolchain.JavaLanguageVersion import javax.inject.Inject /* * Iris is a World Generator for Minecraft Bukkit Servers * Copyright (c) 2021 Arcane Arts (Volmit Software) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ buildscript { repositories { mavenCentral() maven { url = uri('https://jitpack.io') } } dependencies { classpath('com.github.VolmitSoftware.VolmLib:packaging:master-SNAPSHOT') } } plugins { id 'java' id 'java-library' } apply plugin: 'art.arcane.volmit-packaging' apply from: file('gradle/runtime-relocations.gradle') apply from: file('gradle/volmlib-stamp.gradle') interface IrisFileOperations { @Inject FileSystemOperations getFileSystemOperations() } IrisFileOperations irisFileOperations = objects.newInstance(IrisFileOperations) group = 'art.arcane' version = providers.gradleProperty('irisVersion').getOrElse('4.3.3') project(':core') { group = 'art.arcane' version = rootProject.version } apply from: file('gradle/mod-target.gradle') String minecraftVersion = providers.gradleProperty('minecraftVersion').getOrElse('26.3') // The Bukkit jar retains 26.1.2 and 26.2 alongside 26.3. String bukkitMinecraftRange = providers.gradleProperty('bukkitMinecraftRange').getOrElse('26.1.2-26.3') String fabricLoaderVersion = providers.gradleProperty('fabricLoaderVersion').getOrElse(irisModTarget.fabricLoader.toString()) String forgeVersion = providers.gradleProperty('forgeVersion').getOrElse(irisModTarget.forge.toString()) String neoForgeVersion = providers.gradleProperty('neoForgeVersion').getOrElse(irisModTarget.neoForge.toString()) String volmLibShared = 'com.github.VolmitSoftware.VolmLib:volmlib-shared:master-SNAPSHOT' File localVolmLibCheckout = (File) gradle.extensions.extraProperties.get('volmLibDirectory') IncludedBuild localVolmLibBuild = localVolmLibCheckout == null ? null : gradle.includedBuilds.find { IncludedBuild includedBuild -> includedBuild.projectDir.canonicalFile == localVolmLibCheckout.canonicalFile } Map volmLibStamp = (Map) gradle.extensions.extraProperties.get('volmLibStamp') Closure loaderDisplayVersion = { String loaderVersion -> String coordinatePrefix = "${minecraftVersion}-" if (loaderVersion.startsWith(coordinatePrefix)) { return loaderVersion.substring(coordinatePrefix.length()) } return loaderVersion } Closure irisArtifactName = { String platform, String targetVersion -> return "Iris v${project.version} [${platform}] ${targetVersion}.jar" } String bukkitArtifactName = irisArtifactName('CraftBukkit', bukkitMinecraftRange) String fabricArtifactName = irisArtifactName('Fabric', "${minecraftVersion}+${loaderDisplayVersion(fabricLoaderVersion)}") String forgeArtifactName = irisArtifactName('Forge', "${minecraftVersion}+${loaderDisplayVersion(forgeVersion)}") String neoForgeArtifactName = irisArtifactName('NeoForge', "${minecraftVersion}+${loaderDisplayVersion(neoForgeVersion)}") Map runtimeDownloadRelocations = (Map) ext.runtimeDownloadRelocations List runtimeDownloadedPrefixes = (List) ext.runtimeDownloadedPrefixes File pluginOutDirectory = file(providers.gradleProperty('pluginOutDirectory').getOrElse('../PluginOuts')) File legacyBukkitJar = layout.buildDirectory.file("libs/Iris-${project.version}.jar").get().asFile File bukkitArtifact = layout.buildDirectory.file("libs/${bukkitArtifactName}").get().asFile File consumerBukkitArtifact = layout.buildDirectory.file("consumer/${bukkitArtifactName}").get().asFile File fabricArtifact = layout.projectDirectory.file("adapters/fabric/build/${minecraftVersion}/libs/${fabricArtifactName}").asFile File forgeArtifact = layout.projectDirectory.file("adapters/forge/build/${minecraftVersion}/libs/${forgeArtifactName}").asFile File neoForgeArtifact = layout.projectDirectory.file("adapters/neoforge/build/${minecraftVersion}/libs/${neoForgeArtifactName}").asFile File consumerDirectory = layout.buildDirectory.dir('consumer').get().asFile FileTree staleConsumerBukkitJars = fileTree(consumerDirectory) { include('Iris v* [CraftBukkit] *.jar') } Map staleOutJars = [ CraftBukkit: 'Iris v* [CraftBukkit] *.jar', Fabric : "Iris v* [Fabric] ${minecraftVersion}+*.jar", Forge : "Iris v* [Forge] ${minecraftVersion}+*.jar", NeoForge : "Iris v* [NeoForge] ${minecraftVersion}+*.jar" ].collectEntries { String platform, String pattern -> [(platform): fileTree(pluginOutDirectory) { include(pattern) }] } apply plugin: ApiGenerator // Where `buildAll` drops the per-platform jars for a local test server. Use the approved sibling // Multiplexor workspace when it exists, with a repo-local fallback for fresh clones. File multiplexorConsumerLocation = new File(rootDir, '../../[Minecraft Server]/consumers').canonicalFile String defaultConsumerLocation = multiplexorConsumerLocation.isDirectory() ? multiplexorConsumerLocation.absolutePath : layout.buildDirectory.dir('consumers').get().asFile.absolutePath String consumerLocation = providers.gradleProperty('location') .getOrElse(defaultConsumerLocation) String bukkitConsumerPath = "${consumerLocation}/plugin-consumers/dropins/plugins" String fabricConsumerPath = "${consumerLocation}/fabric-mod-consumers/dropins/mods" String forgeConsumerPath = "${consumerLocation}/forge-mod-consumers/dropins/mods" String neoForgeConsumerPath = "${consumerLocation}/neoforge-mod-consumers/dropins/mods" List nmsBindings = ['v26_2_R1', 'v26_3_R1'] ext.nativeDevelopmentAdapters = nmsBindings nmsBindings.each { String key -> project(":adapters:bukkit:nms:${key}") { apply plugin: JavaPlugin apply plugin: PaperweightUser if (localVolmLibBuild != null) { tasks.named('paperweightUserdevSetup').configure { dependsOn(localVolmLibBuild.task(":native:${key}:paperweightUserdevSetup")) if (key == 'v26_2_R1') { dependsOn(localVolmLibBuild.task(':native-common:paperweightUserdevSetup')) } } } NativeDevelopmentTargets.Target nativeTarget = NativeDevelopmentTargets.require(key) dependencies.extensions.getByType(PaperweightUserDependenciesExtension) .paperDevBundle(nativeTarget.paperBundle()) JavaPluginExtension javaExtension = extensions.getByType(JavaPluginExtension) javaExtension.toolchain.languageVersion.set(JavaLanguageVersion.of(nativeTarget.javaVersion())) JavaToolchainService nativeToolchains = extensions.getByType(JavaToolchainService) extensions.configure(PaperweightUserExtension) { PaperweightUserExtension extension -> extension.javaLauncher.set(nativeToolchains.launcherFor(javaExtension.toolchain)) } dependencies { implementation("com.github.VolmitSoftware.VolmLib:native-${key}:master-SNAPSHOT") { transitive = false } compileOnly(project(':core')) compileOnly(volmLibShared) { transitive = false } compileOnly(rootProject.libs.annotations) compileOnly(rootProject.libs.byteBuddy.core) testImplementation('junit:junit:4.13.2') testImplementation('org.mockito:mockito-core:5.23.0') if (key == 'v26_3_R1') { testImplementation(project(':probe')) } testImplementation(project(':core')) testImplementation(testFixtures(project(':core'))) testImplementation('com.github.VolmitSoftware.VolmLib:native-common:master-SNAPSHOT') { transitive = false } testCompileOnly(volmLibShared) { transitive = false } testRuntimeOnly(project(':core')) testRuntimeOnly(rootProject.libs.caffeine) } } } def included = configurations.create('included') def nativeRuntime = configurations.create('nativeRuntime') def nativeRuntimeOutput = layout.buildDirectory.dir('generated/native-runtime') def nativeRuntimeRules = layout.buildDirectory.file('generated/native-runtime-keep.pro') List nativeRuntimeModules = ['native-common'] + nmsBindings.collect { String adapter -> 'native-' + adapter } dependencies { nativeRuntimeModules.each { String module -> add('nativeRuntime', "com.github.VolmitSoftware.VolmLib:${module}:master-SNAPSHOT") { transitive = false } } } // The natives PackedJar embeds are the single source for the runtime manifest, the reachability roots and // the ProGuard keep rules, so the shrinker can never prune against a different provider build. Closure> embeddedNatives = { -> Map resolved = new LinkedHashMap<>() nativeRuntime.incoming.artifacts.artifacts.each { artifact -> resolved.put(artifact.id.componentIdentifier, artifact.file) } return PackedJar.resolveNativeArtifacts(resolved) } def generateNativeRuntime = tasks.register('generateNativeRuntime') { inputs.files(nativeRuntime) inputs.property('modules', nativeRuntimeModules) outputs.dir(nativeRuntimeOutput) outputs.file(nativeRuntimeRules) doLast { NativeRuntimeArtifacts.generate(embeddedNatives(), nativeRuntimeModules, nativeRuntimeOutput.get().asFile, nativeRuntimeRules.get().asFile) } } def jarJar = configurations.create('jarJar') dependencies { add('included', project(path: ':core', configuration: 'shadow')) add('included', project(path: ':adapters:bukkit:plugin', configuration: 'runtimeElements')) add('jarJar', project(':core:agent')) } tasks.named('jar', Jar).configure { inputs.files(included) dependsOn(generateNativeRuntime) from(nativeRuntimeOutput) from(tasks.named('generateVolmLibStamp')) { into('META-INF/volmit') } duplicatesStrategy = DuplicatesStrategy.EXCLUDE includeEmptyDirs = false from(jarJar) from(provider { included.resolve().collect { zipTree(it) } }) { exclude('languages/**') exclude('com/fren_gor/**') } doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(legacyBukkitJar) } } archiveFileName.set(bukkitArtifactName) } tasks.register('iris', Copy) { group = 'iris' dependsOn('packedJar') from({ tasks.named('packedJar').get().outputJar }) rename { String ignored -> bukkitArtifactName } into(layout.buildDirectory.dir('consumer')) doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(staleConsumerBukkitJars) } } } tasks.register('buildSwiftSwamp') { group = 'iris' description = 'Builds every platform jar and drops them in the local BUILDS output directory.' outputs.upToDateWhen { false } dependsOn('iris', 'verifyModdedArtifacts') File swiftSwampOut = file('C://VolmitSoftware/BUILDS') Map swiftSwampSources = [ 'Iris.jar' : consumerBukkitArtifact, 'Iris-Fabric.jar' : fabricArtifact, 'Iris-Forge.jar' : forgeArtifact, 'Iris-Neoforge.jar': neoForgeArtifact ] doLast { swiftSwampSources.each { String target, File source -> irisFileOperations.fileSystemOperations.copy { CopySpec spec -> spec.from(source) spec.into(swiftSwampOut) spec.rename { String ignored -> target } } } println('') println('=== Iris buildSwiftSwamp -> ' + swiftSwampOut + ' ===') ['Iris.jar', 'Iris-Fabric.jar', 'Iris-Forge.jar', 'Iris-Neoforge.jar'].each { String jar -> File produced = new File(swiftSwampOut, jar) println(String.format(' %-24s %8d KB', jar, (long) (produced.length() / 1024))) } } } tasks.register('buildBukkit', Copy) { group = 'iris' dependsOn('packedJar') from({ tasks.named('packedJar').get().outputJar }) rename { String ignored -> bukkitArtifactName } into(pluginOutDirectory) File legacyOutJar = new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}.jar") doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(staleOutJars['CraftBukkit'], legacyOutJar) } } } // The three loader jars come out of nested standalone Gradle builds driven through Exec. The outer // task therefore has to carry the full inventory of what those builds read: every shared source tree, // every build script and version file they load, and the local VolmLib checkout when the composite // resolves one. Anything missing from that list publishes a stale jar. List moddedSharedInputs = [] [ 'adapters/modded-common/src', 'adapters/client-common/src', 'core/src/main', 'core/build.gradle', 'core/agent/src', 'core/agent/build.gradle', 'spi/src/main', 'spi/build.gradle', 'build.gradle', 'settings.gradle', 'gradle.properties', 'lombok.config', 'gradle/libs.versions.toml', 'gradle/volmlib-resolution.settings.gradle', 'gradle/volmlib-stamp.gradle', 'gradle/generation-build-revision.gradle', 'gradle/modded-generation-build-revision.gradle', 'gradle/native-minecraft-sources.gradle', 'gradle/mod-target.gradle', 'gradle/mod-targets.json', 'gradle/modded-version-sources.gradle' ].each { String path -> moddedSharedInputs.add(layout.projectDirectory.file(path).asFile) } if (localVolmLibCheckout != null) { moddedSharedInputs.add(fileTree(localVolmLibCheckout) { include('shared/src/main/**', 'native-api/src/main/**', 'native-terrain-api/src/main/**', 'native/**/src/main/**', 'native/minecraft-common/src/**', 'packaging/src/main/**', '**/build.gradle', 'settings.gradle', 'gradle.properties', 'gradle/libs.versions.toml') exclude('**/build/**', '**/.gradle/**') }) } // The published master-SNAPSHOT is resolved inside the nested build, so no outer input changes when it // moves. Without a local checkout the Exec tasks always run and the nested build decides what is stale. Closure declareVolmLibInputs = { Exec task -> task.inputs.property('volmLibStamp', volmLibStamp) String nativeBillow = providers.gradleProperty('includeNativeBillow').getOrElse('false') task.inputs.property('includeNativeBillow', nativeBillow) task.environment('ORG_GRADLE_PROJECT_includeNativeBillow', nativeBillow) if (localVolmLibCheckout == null) { task.outputs.upToDateWhen { false } } return null } Closure declareModdedJarIo = { Exec task, String adapter, String artifactName, Map versions -> task.inputs.files(moddedSharedInputs).withPropertyName('moddedSharedSources') .withPathSensitivity(PathSensitivity.RELATIVE) task.inputs.files( layout.projectDirectory.file("adapters/${adapter}/src").asFile, layout.projectDirectory.file("adapters/${adapter}/build.gradle").asFile, layout.projectDirectory.file("adapters/${adapter}/settings.gradle").asFile ).withPropertyName('adapterSources') versions.each { String key, String value -> task.inputs.property(key, value) } declareVolmLibInputs(task) task.outputs.file(layout.projectDirectory.file("adapters/${adapter}/build/${minecraftVersion}/libs/${artifactName}")) return null } tasks.register('fabricJar', Exec) { group = 'iris' workingDir = layout.projectDirectory.dir('adapters/fabric').asFile String wrapperScript = System.getProperty('os.name').toLowerCase().contains('windows') ? 'gradlew.bat' : 'gradlew' List command = [ layout.projectDirectory.file(wrapperScript).asFile.absolutePath, 'assemble', '--console=plain', "-PirisVersion=${project.version}", "-PminecraftVersion=${minecraftVersion}", "-PfabricLoaderVersion=${fabricLoaderVersion}", "-PuseLocalVolmLib=${localVolmLibCheckout != null}" ] if (localVolmLibCheckout != null) { environment('ORG_GRADLE_PROJECT_localVolmLibDirectory', localVolmLibCheckout.absolutePath) } commandLine(command) declareModdedJarIo(it, 'fabric', fabricArtifactName, [ irisVersion: project.version.toString(), minecraftVersion: minecraftVersion, fabricLoaderVersion: fabricLoaderVersion ]) } tasks.register('buildFabric', Copy) { group = 'iris' dependsOn('fabricJar') from(layout.projectDirectory.file("adapters/fabric/build/${minecraftVersion}/libs/${fabricArtifactName}")) into(pluginOutDirectory) File legacyOutJar = new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-fabric.jar") doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(staleOutJars['Fabric'], legacyOutJar) } } } tasks.register('forgeJar', Exec) { group = 'iris' workingDir = layout.projectDirectory.dir('adapters/forge').asFile String wrapperScript = System.getProperty('os.name').toLowerCase().contains('windows') ? 'gradlew.bat' : 'gradlew' List command = [ layout.projectDirectory.file(wrapperScript).asFile.absolutePath, 'assemble', '--console=plain', "-PirisVersion=${project.version}", "-PminecraftVersion=${minecraftVersion}", "-PforgeVersion=${forgeVersion}", "-PuseLocalVolmLib=${localVolmLibCheckout != null}" ] if (localVolmLibCheckout != null) { environment('ORG_GRADLE_PROJECT_localVolmLibDirectory', localVolmLibCheckout.absolutePath) } commandLine(command) declareModdedJarIo(it, 'forge', forgeArtifactName, [ irisVersion: project.version.toString(), minecraftVersion: minecraftVersion, forgeVersion: forgeVersion ]) } tasks.register('buildForge', Copy) { group = 'iris' dependsOn('forgeJar') from(layout.projectDirectory.file("adapters/forge/build/${minecraftVersion}/libs/${forgeArtifactName}")) into(pluginOutDirectory) File legacyOutJar = new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-forge.jar") doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(staleOutJars['Forge'], legacyOutJar) } } } tasks.register('neoforgeJar', Exec) { group = 'iris' workingDir = layout.projectDirectory.dir('adapters/neoforge').asFile String wrapperScript = System.getProperty('os.name').toLowerCase().contains('windows') ? 'gradlew.bat' : 'gradlew' List command = [ layout.projectDirectory.file(wrapperScript).asFile.absolutePath, 'assemble', '--console=plain', "-PirisVersion=${project.version}", "-PminecraftVersion=${minecraftVersion}", "-PneoForgeVersion=${neoForgeVersion}", "-PuseLocalVolmLib=${localVolmLibCheckout != null}" ] if (localVolmLibCheckout != null) { environment('ORG_GRADLE_PROJECT_localVolmLibDirectory', localVolmLibCheckout.absolutePath) } commandLine(command) declareModdedJarIo(it, 'neoforge', neoForgeArtifactName, [ irisVersion: project.version.toString(), minecraftVersion: minecraftVersion, neoForgeVersion: neoForgeVersion ]) } tasks.register('buildNeoforge', Copy) { group = 'iris' dependsOn('neoforgeJar') from(layout.projectDirectory.file("adapters/neoforge/build/${minecraftVersion}/libs/${neoForgeArtifactName}")) into(pluginOutDirectory) File legacyOutJar = new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-neoforge.jar") doFirst { irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> spec.delete(staleOutJars['NeoForge'], legacyOutJar) } } } tasks.named('forgeJar').configure { mustRunAfter(tasks.named('fabricJar')) } tasks.named('fabricJar').configure { mustRunAfter(tasks.named('jar')) mustRunAfter(tasks.named('buildBukkit')) mustRunAfter(project(':spi').tasks.named('jar')) } tasks.named('neoforgeJar').configure { mustRunAfter(tasks.named('forgeJar')) } // adapters/modded-common has no build of its own: its sources are compiled by each loader wrapper, so // its tests only run when one of those wrappers is asked for `test`. The Fabric wrapper is the one // that runs them as plain JUnit - NeoForge's moddev unit-test harness boots the mod through FML's // transforming class loader and dies on a split-package ServiceConfigurationError before any test // starts. One loader is enough: the sources are identical across all three. tasks.register('moddedTest', Exec) { group = 'verification' description = 'Runs the adapters/modded-common test suite through the Fabric adapter build.' workingDir = layout.projectDirectory.dir('adapters/fabric').asFile String wrapperScript = System.getProperty('os.name').toLowerCase().contains('windows') ? 'gradlew.bat' : 'gradlew' List command = [ layout.projectDirectory.file(wrapperScript).asFile.absolutePath, 'test', '--console=plain', "-PirisVersion=${project.version}", "-PminecraftVersion=${minecraftVersion}", "-PfabricLoaderVersion=${fabricLoaderVersion}", "-PuseLocalVolmLib=${localVolmLibCheckout != null}" ] if (localVolmLibCheckout != null) { environment('ORG_GRADLE_PROJECT_localVolmLibDirectory', localVolmLibCheckout.absolutePath) } commandLine(command) inputs.files(moddedSharedInputs).withPropertyName('moddedSharedSources') .withPathSensitivity(PathSensitivity.RELATIVE) inputs.files( layout.projectDirectory.file('adapters/fabric/src').asFile, layout.projectDirectory.file('adapters/fabric/build.gradle').asFile, layout.projectDirectory.file('adapters/fabric/settings.gradle').asFile ).withPropertyName('adapterSources') inputs.property('irisVersion', project.version.toString()) inputs.property('minecraftVersion', minecraftVersion) inputs.property('fabricLoaderVersion', fabricLoaderVersion) declareVolmLibInputs(it) outputs.dir(layout.projectDirectory.dir("adapters/fabric/build/${minecraftVersion}/test-results/test")) mustRunAfter(tasks.named('jar')) mustRunAfter(project(':core').tasks.named('check')) mustRunAfter(project(':spi').tasks.named('jar')) } tasks.named('fabricJar').configure { mustRunAfter(tasks.named('moddedTest')) } gradle.projectsEvaluated { List sharedOutputTasks = allprojects.collectMany { Project candidate -> candidate.tasks.findAll { Task task -> task instanceof JavaCompile || task instanceof Jar || task instanceof Test } } for (String taskName : ['moddedTest', 'fabricJar', 'forgeJar', 'neoforgeJar']) { tasks.named(taskName).configure { mustRunAfter(sharedOutputTasks) } } } tasks.named('check').configure { dependsOn('moddedTest') } List commonModdedArtifactEntries = [ 'agent.jar', 'pack.mcmeta', 'com/fulcrumgenomics/jlibdeflate/LibdeflateDecompressor.class', 'com/fulcrumgenomics/jlibdeflate/LibdeflateException.class', 'native/linux-aarch64/libjlibdeflate.so', 'native/linux-x86_64/libjlibdeflate.so', 'native/osx-aarch64/libjlibdeflate.dylib', 'native/osx-x86_64/libjlibdeflate.dylib', 'native/windows-x86_64/jlibdeflate.dll', 'META-INF/iris/generation-kernels/catalog.tsv', 'META-INF/iris/generation-kernels/abi-1.revision', 'META-INF/volmit/volmlib.properties', 'META-INF/services/art.arcane.iris.localization.IrisMessageContributor', 'art/arcane/iris/generation/runtime/IrisEngine.class', 'art/arcane/iris/pack/datapack/DataVersion.class', 'art/arcane/iris/pack/datapack/IDataFixer.class', 'art/arcane/iris/spi/IrisPlatform.class', 'art/arcane/volmlib/util/mantle/io/Lz4IOWorkerCodecSupport.class', 'art/arcane/iris/platform/bootstrap/getHardware.class', // Both shared mixin configs plus the lang file and mod icon every loader's metadata points at. // A shadowJar exclude or a renamed resource that drops any of these is silent at build time and // shows up as a non-applied mixin or a missing-translation report from a user. 'volmlib.entity.mixins.json', 'volmlib.client.mixins.json', 'art/arcane/volmlib/nativelib/minecraft26_2/client/mixin/NativeWorldOpenFlowsMixin.class', 'art/arcane/volmlib/nativelib/minecraft26_2/client/mixin/NativeWorldTypeEntryMixin.class', 'assets/irisworldgen/lang/en_us.json', 'assets/irisworldgen/icon.png' ] // The modded jars ship the Bukkit-only code paths inert - excluding them means chasing the whole core // reference graph. What must not slip in is new Bukkit coupling in core, which core already declares // in purity-allowlist.txt, so the baseline is read from there instead of frozen by hand. File bukkitPurityAllowlist = layout.projectDirectory.file('core/purity-allowlist.txt').asFile Set bukkitCoupledCoreClasses = bukkitPurityAllowlist.readLines() .findAll { String line -> !line.isBlank() } .collect { String line -> line.trim() - ~/\.java$/ } .toSet() tasks.register('verifyFabricArtifact') { group = 'verification' dependsOn('fabricJar') File artifact = fabricArtifact inputs.file(artifact) inputs.file(bukkitPurityAllowlist) doLast { List requiredEntries = commonModdedArtifactEntries + [ 'fabric.mod.json', 'volmlib.fabric.mixins.json', 'volmlib.accesswidener', 'art/arcane/iris/fabric/IrisFabricBootstrap.class' ] ModdedArtifactVerifier.verify(artifact, requiredEntries, bukkitCoupledCoreClasses) ModdedArtifactVerifier.verifyJavaRuntime(artifact, (int) irisModTarget.java) logger.lifecycle("Verified ${artifact.name} packaging, mixin compat, and nested jars") } } tasks.register('verifyForgeArtifact') { group = 'verification' dependsOn('forgeJar') File artifact = forgeArtifact inputs.file(artifact) inputs.file(bukkitPurityAllowlist) doLast { List requiredEntries = commonModdedArtifactEntries + [ 'META-INF/mods.toml', 'META-INF/accesstransformer.cfg', 'art/arcane/iris/forge/IrisForgeBootstrap.class' ] ModdedArtifactVerifier.verify(artifact, requiredEntries, bukkitCoupledCoreClasses) ModdedArtifactVerifier.verifyJavaRuntime(artifact, (int) irisModTarget.java) logger.lifecycle("Verified ${artifact.name} packaging, mixin compat, and nested jars") } } tasks.register('verifyNeoforgeArtifact') { group = 'verification' dependsOn('neoforgeJar') File artifact = neoForgeArtifact inputs.file(artifact) inputs.file(bukkitPurityAllowlist) doLast { List requiredEntries = commonModdedArtifactEntries + [ 'META-INF/neoforge.mods.toml', 'META-INF/accesstransformer.cfg', 'art/arcane/iris/neoforge/IrisNeoForgeBootstrap.class' ] ModdedArtifactVerifier.verify(artifact, requiredEntries, bukkitCoupledCoreClasses) ModdedArtifactVerifier.verifyJavaRuntime(artifact, (int) irisModTarget.java) logger.lifecycle("Verified ${artifact.name} packaging, mixin compat, and nested jars") } } tasks.register('verifyModdedArtifacts') { group = 'verification' dependsOn('verifyFabricArtifact', 'verifyForgeArtifact', 'verifyNeoforgeArtifact') } TaskProvider verifyModdedMatrix = tasks.register('verifyModdedMatrix') { group = 'verification' description = 'Builds and verifies every supported Minecraft mod target and runs the shared mod tests.' } TaskProvider previousMatrixBuild = null irisModTargets.each { String targetMinecraft, Map target -> ['fabric': 'Fabric', 'forge': 'Forge', 'neoforge': 'NeoForge'].each { String loader, String label -> String pinKey = loader == 'fabric' ? 'fabricLoader' : loader == 'neoforge' ? 'neoForge' : 'forge' String loaderPin = target.get(pinKey).toString() String displayedLoader = loaderPin.startsWith(targetMinecraft + '-') ? loaderPin.substring(targetMinecraft.length() + 1) : loaderPin String artifactName = irisArtifactName(label, "${targetMinecraft}+${displayedLoader}") File artifact = file("adapters/${loader}/build/${targetMinecraft}/libs/${artifactName}") TaskProvider buildTarget = tasks.register("verify${label}${targetMinecraft.replace('.', '_')}", Exec) { group = 'verification' workingDir = file("adapters/${loader}") String wrapperScript = System.getProperty('os.name').toLowerCase().contains('windows') ? 'gradlew.bat' : 'gradlew' List command = [file(wrapperScript).absolutePath, 'assemble', 'compileTestJava', 'verifyLoggingPolicy', 'verifyNativeClassBoundary', '--console=plain', "-PirisVersion=${project.version}", "-PminecraftVersion=${targetMinecraft}", "-PuseLocalVolmLib=${localVolmLibCheckout != null}"] if (loader == 'fabric') { command.add('test') } commandLine(command) if (localVolmLibCheckout != null) { environment('ORG_GRADLE_PROJECT_localVolmLibDirectory', localVolmLibCheckout.absolutePath) } inputs.files(moddedSharedInputs, file("adapters/${loader}/src"), file("adapters/${loader}/build.gradle"), file("adapters/${loader}/settings.gradle")) inputs.properties(target) declareVolmLibInputs(it) outputs.file(artifact) if (loader == 'fabric') { outputs.dir(file("adapters/${loader}/build/${targetMinecraft}/test-results/test")) } doLast { String metadata = loader == 'fabric' ? 'fabric.mod.json' : loader == 'forge' ? 'META-INF/mods.toml' : 'META-INF/neoforge.mods.toml' ModdedArtifactVerifier.verify(artifact, commonModdedArtifactEntries + [metadata], bukkitCoupledCoreClasses) ModdedArtifactVerifier.verifyJavaRuntime(artifact, (int) target.java) logger.lifecycle("Verified ${artifact.name}") } } if (previousMatrixBuild != null) { TaskProvider preceding = previousMatrixBuild buildTarget.configure { mustRunAfter(preceding) } } previousMatrixBuild = buildTarget verifyModdedMatrix.configure { dependsOn(buildTarget) } } } // Entries the Bukkit artifact only ever reaches by name - NMS binding lookup, the SIMD kernels, the // instrumentation agent, the JarScanner-driven command and service discovery, the Matter codec - plus // the two plugin descriptors and the slimjar manifests. Nothing in the reference graph points at // them, so a shadowJar exclude that drops one is silent until a server hits that path. File commandSourceRoot = layout.projectDirectory.dir('core/src/main/java').asFile FileTree commandHandlerSources = fileTree(commandSourceRoot) { include('art/arcane/iris/command/handlers/**/*.java') include('art/arcane/iris/command/context/**/*.java') include('art/arcane/iris/command/specialhandlers/**/*.java') } List requiredCommandHandlerEntries = commandHandlerSources.files.collect { File source -> commandSourceRoot.toPath().relativize(source.toPath()).toString() .replace(File.separator, '/').replaceAll(/\.java$/, '.class') }.sort() FileTree mantleComponentSources = fileTree(commandSourceRoot) { include('art/arcane/iris/generation/mantle/**/*.java') } List requiredMantleComponentEntries = mantleComponentSources.files.findAll { File source -> source.getText('UTF-8') =~ /(?m)^\s*@ComponentFlag\b/ }.collect { File source -> commandSourceRoot.toPath().relativize(source.toPath()).toString() .replace(File.separator, '/').replaceAll(/\.java$/, '.class') }.sort() List requiredBukkitArtifactEntries = [ 'META-INF/iris/generation-kernels/catalog.tsv', 'META-INF/iris/generation-kernels/abi-1.revision', 'plugin.yml', 'paper-plugin.yml', 'slimjar.dat', 'slimjar-resolutions.dat', 'META-INF/iris/native-runtime.properties', 'META-INF/volmit/volmlib.properties', 'iris-language-source.properties', 'agent.jar', 'art/arcane/iris/Iris.class', 'art/arcane/iris/IrisBootstrap.class', 'art/arcane/iris/platform/bukkit/nms/INMS.class', 'art/arcane/iris/platform/bukkit/nms/BukkitBinding.class', 'art/arcane/volmlib/nativelib/NativeAdapters.class', 'art/arcane/volmlib/nativelib/terrain/NativeWorldGeneration.class', 'art/arcane/iris/platform/bukkit/nms/v1X/NMSBinding1X.class', 'art/arcane/iris/platform/generation/PlatformChunkGenerator.class', 'art/arcane/iris/world/lifecycle/WorldLifecycleStaging.class', 'art/arcane/iris/generation/simd/VectorSimdKernels.class', 'art/arcane/iris/platform/agent/Agent.class', 'art/arcane/iris/platform/bootstrap/getHardware.class', 'art/arcane/volmlib/util/io/JarScanner.class', 'art/arcane/volmlib/util/director/runtime/DirectorRuntimeEngine.class', 'art/arcane/volmlib/util/mantle/io/Lz4IOWorkerCodecSupport.class', 'art/arcane/volmlib/util/matter/Matter.class' ] + requiredCommandHandlerEntries + requiredMantleComponentEntries tasks.register('verifyBukkitArtifact') { group = 'verification' dependsOn('jar') File artifact = bukkitArtifact inputs.file(artifact) inputs.files(nativeRuntime) inputs.files(commandHandlerSources) inputs.files(mantleComponentSources) doLast { BukkitArtifactVerifier.verify( artifact, requiredBukkitArtifactEntries, 16, runtimeDownloadedPrefixes) NativeRuntimeArtifacts.verify(artifact, nativeRuntimeModules, embeddedNatives()) logger.lifecycle("Verified ${artifact.name} packaging and class reference graph") } } tasks.named('buildBukkit').configure { dependsOn('verifyBukkitArtifact') } tasks.named('iris').configure { dependsOn('verifyBukkitArtifact') } tasks.named('buildFabric').configure { dependsOn('verifyFabricArtifact') } tasks.named('buildForge').configure { dependsOn('verifyForgeArtifact') } tasks.named('buildNeoforge').configure { dependsOn('verifyNeoforgeArtifact') } tasks.register('buildAllToOut') { group = 'iris' dependsOn('buildBukkit', 'buildFabric', 'buildForge', 'buildNeoforge', ':spi:jar') doLast { File[] jars = pluginOutDirectory.listFiles((java.io.FileFilter) { File f -> f.name.startsWith('Iris v') && f.name.endsWith('.jar') }) println('') println('=== Iris buildAllToOut -> ' + pluginOutDirectory + ' ===') if (jars != null) { jars.sort { it.name }.each { File f -> println(String.format(' %-60s %8d KB', f.name, (long) (f.length() / 1024))) } } } } tasks.register('buildAll') { group = 'iris' outputs.upToDateWhen { false } dependsOn('iris', 'verifyModdedArtifacts', 'buildAllToOut') Map> consumerDrops = [ (bukkitConsumerPath) : ['Iris.jar', consumerBukkitArtifact], (fabricConsumerPath) : ['Iris-Fabric.jar', fabricArtifact], (forgeConsumerPath) : ['Iris-Forge.jar', forgeArtifact], (neoForgeConsumerPath): ['Iris-Neoforge.jar', neoForgeArtifact] ] doLast { consumerDrops.each { String consumerPath, List drop -> String keep = (String) drop.get(0) File source = (File) drop.get(1) irisFileOperations.fileSystemOperations.delete { DeleteSpec spec -> consumerDrops.values().each { List other -> String name = (String) other.get(0) if (name != keep) { spec.delete(new File(consumerPath, name)) } } } irisFileOperations.fileSystemOperations.copy { CopySpec spec -> spec.from(source) spec.into(consumerPath) spec.rename { String ignored -> keep } } } println('') println("=== Iris buildAll -> ${consumerLocation} ===") println(" ${bukkitConsumerPath}/Iris.jar") println(" ${fabricConsumerPath}/Iris-Fabric.jar") println(" ${forgeConsumerPath}/Iris-Forge.jar") println(" ${neoForgeConsumerPath}/Iris-Neoforge.jar") } } tasks.register('buildPsychoLT') { group = 'development' description = 'Builds all verified Iris platform jars and stages them in the local test-server dropins and PluginOuts.' dependsOn('buildAll') } tasks.register('irisDev', Copy) { group = 'iris' from(project(':core').layout.buildDirectory.files('libs/core-javadoc.jar', 'libs/core-sources.jar')) rename { String fileName -> fileName.replace('core', "Iris-${project.version}") } into(layout.buildDirectory) dependsOn(':core:sourcesJar') dependsOn(':core:javadocJar') } int defaultTestForks = Math.min(8, Math.max(1, Runtime.runtime.availableProcessors().intdiv(2))) int testForks = Math.max(1, Integer.parseInt(providers.gradleProperty('testForks') .getOrElse(String.valueOf(defaultTestForks)))) int irisRuntimeJava = providers.gradleProperty('irisRuntimeJava').getOrElse(irisModTarget.java.toString()).toInteger() if (!(irisRuntimeJava in [21, 25])) { throw new GradleException('irisRuntimeJava must be 21 or 25') } Set sharedRuntimeProjects = [':core', ':core:agent', ':spi'] as Set allprojects { apply plugin: 'java' boolean java21Runtime = irisRuntimeJava == 21 && sharedRuntimeProjects.contains(project.path) if (java21Runtime) { layout.buildDirectory.set(layout.projectDirectory.dir('build/java21')) } tasks.withType(Test).configureEach { int moduleForks = project.path.startsWith(':adapters:bukkit:') ? Math.min(2, testForks) : project.path == ':probe' ? Math.min(4, testForks) : testForks maxParallelForks = Math.min(gradle.startParameter.maxWorkerCount, moduleForks) jvmArgs('-XX:ParallelGCThreads=2', '-XX:ConcGCThreads=1', '-XX:CICompilerCount=2') } java { toolchain { languageVersion = JavaLanguageVersion.of(25) } if (java21Runtime) { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } } if (java21Runtime) { Provider runtimeLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(21) } tasks.withType(JavaCompile).configureEach { sourceCompatibility = '21' targetCompatibility = '21' if (project.path == ':core') { options.compilerArgumentProviders.add({ ['--system', runtimeLauncher.get().metadata.installationPath.asFile.absolutePath] } as org.gradle.process.CommandLineArgumentProvider) } else { options.release.set(21) } } if (project.path != ':core') { tasks.withType(Test).configureEach { javaLauncher.set(runtimeLauncher) } } } repositories { mavenCentral() maven { url = uri('https://repo.papermc.io/repository/maven-public/') } maven { url = uri('https://repo.codemc.org/repository/maven-public/') } maven { url = uri('https://jitpack.io') content { includeGroupByRegex('com\\.github\\..*') } } // score maven { url = uri('https://repo.auxilor.io/repository/maven-releases/') content { includeGroupByRegex('com\\.willfp(\\..*)?') } } // eco maven { url = uri('https://repo.nexomc.com/releases/') content { includeGroup('com.nexomc') includeGroup('team.unnamed') } } // nexo maven { url = uri('https://repo.oraxen.com/releases/') content { includeGroup('io.th0rgal') } } maven { url = uri('https://repo.extendedclip.com/releases/') content { includeGroup('me.clip') } } // placeholderapi maven { url = uri('https://mvn.lumine.io/repository/maven-public/') content { includeModule('io.lumine', 'Mythic-Dist') includeModule('io.lumine', 'MythicCrucible-Dist') } } // mythic maven { url = uri('https://nexus.phoenixdevt.fr/repository/maven-public/') content { includeGroup('net.Indyuce') includeModule('io.lumine', 'MythicLib-dist') } } //MMOItems maven { url = uri('https://repo.onarandombox.com/content/groups/public/') content { includeGroupByRegex('org\\.mvplugins\\.multiverse(\\..*)?') } } //Multiverse Core maven { url = uri('https://repo.momirealms.net/releases/') content { includeGroup('net.momirealms') } } // CraftEngine } /** * We need parameter meta for the decree command system */ tasks.named('compileJava', JavaCompile).configure { options.compilerArgs.add('-parameters') options.encoding = 'UTF-8' options.debugOptions.debugLevel = 'none' if (!java21Runtime) { options.release.set(25) } } tasks.named('javadoc').configure { options.encoding = 'UTF-8' options.quiet() //options.addStringOption("Xdoclint:none") // TODO: Re-enable this } tasks.register('sourcesJar', Jar) { archiveClassifier.set('sources') from(sourceSets.main.allSource) } tasks.register('javadocJar', Jar) { archiveClassifier.set('javadoc') from(tasks.named('javadoc').map { it.destinationDir }) } } if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_25)) { System.err.println() System.err.println('=========================================================================================================') System.err.println('You must run gradle on Java 25 or newer. You are using ' + JavaVersion.current()) System.err.println() System.err.println('=== For IDEs ===') System.err.println('1. Configure the project for Java 25 toolchain') System.err.println('2. Configure the bundled gradle to use Java 25+ in settings') System.err.println() System.err.println('=== For Command Line (gradlew) ===') System.err.println('1. Install JDK 25 from https://adoptium.net/temurin/releases/?version=25') System.err.println('2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-25') System.err.println('3. Open a new command prompt window to get the new environment variables if need be.') System.err.println('=========================================================================================================') System.err.println() System.exit(69) } pluginPackaging { artifacts { create('distribution') { taskName = 'jar' policyName = 'Iris Bukkit' packed = true packedJarAccessors = ['art/arcane/iris/platform/bukkit/plugin/VolmitPlugin#getJarFile'] stripDirectories = true stripLocalVariables = true releaseCompression = providers.gradleProperty('compactRelease') .map { String value -> value.toBoolean() } .getOrElse(!PackagingMode.resolve(providers).development()) prunePrefixes = ['art/arcane/volmlib/'] keepPrefixes = ['art/arcane/volmlib/util/matter/slices/', 'art/arcane/volmlib/nativelib/'] shrinkRules = [file('packaging/shrink.pro'), nativeRuntimeRules.get().asFile] shrinkDontwarn = [ 'java.lang.invoke.MethodHandle', 'java.lang.invoke.VarHandle', 'net.minecraft.server.MinecraftServer', 'net.minecraft.server.level.ServerLevel', 'net.minecraft.world.attribute.EnvironmentAttributes', 'net.minecraft.world.level.NaturalSpawner', 'net.minecraft.world.level.StructureManager', 'net.minecraft.world.level.biome.BiomeManager', 'net.minecraft.world.level.biome.BiomeResolver', 'net.minecraft.world.level.biome.BiomeSource', 'net.minecraft.world.level.biome.MobSpawnSettings', 'net.minecraft.world.level.biome.MobSpawnSettings$SpawnerData', 'net.minecraft.world.level.chunk.ChunkAccess', 'net.minecraft.world.level.chunk.ChunkGenerator', 'net.minecraft.world.level.chunk.status.ChunkStatus', 'net.minecraft.world.level.levelgen.RandomState', 'net.minecraft.world.level.levelgen.feature.Feature', 'net.minecraft.world.level.levelgen.structure.Structure', 'net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement', 'net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement', 'org.bukkit.craftbukkit.inventory.CraftItemStack', ] shrinkLibraries.from(provider { project(':core').configurations.compileClasspath }) shrinkLibraries.from(provider { project(':adapters:bukkit:plugin').configurations.compileClasspath }) nmsBindings.each { binding -> shrinkLibraries.from(provider { project(":adapters:bukkit:nms:${binding}").configurations.compileClasspath.incoming.artifactView { Set nativeComponents = nativeRuntime.incoming.artifacts.artifacts.collect { artifact -> artifact.id.componentIdentifier }.toSet() componentFilter { component -> !nativeComponents.contains(component) } }.files }) } shrinkRelocations = runtimeDownloadRelocations } } } project(':adapters:bukkit:nms:v26_3_R1') { Configuration headlessNativeSources = configurations.create('headlessNativeSources') { canBeConsumed = false canBeResolved = true } dependencies.add(headlessNativeSources.name, 'com.github.VolmitSoftware.VolmLib:native-minecraft26_2-sources:master-SNAPSHOT') List headlessNativeTypes = ['ModdedBlockState', 'ModdedBiome', 'NativeBlockProperties', 'NativeBlockResolver', 'NativeBlockFaces', 'NativeStateRotator', 'NativeStateMerger', 'NativeRegistryAccess', 'ModdedItem', 'ModdedEntityType', 'NativeTileReader', 'NativeTileData'] TaskProvider unpackHeadlessNativeSources = tasks.register('unpackHeadlessNativeSources', Sync) { dependsOn(headlessNativeSources) inputs.property('nativeTypes', headlessNativeTypes) from(provider { headlessNativeSources.collect { File artifact -> zipTree(artifact) } }) { headlessNativeTypes.each { String type -> include("art/arcane/volmlib/nativelib/minecraft26_2/modded/${type}.java") } } from(rootProject.file('adapters/modded-common/src/main/java')) { include('art/arcane/iris/modded/ModdedDecoratorHooks.java', 'art/arcane/iris/modded/ModdedStateRotator.java', 'art/arcane/iris/modded/ModdedTileData.java') } into(layout.buildDirectory.dir('generated/sources/headless-native')) } sourceSets { offline { java.srcDir(unpackHeadlessNativeSources) compileClasspath += sourceSets.main.compileClasspath runtimeClasspath += sourceSets.main.compileClasspath + sourceSets.main.output } } dependencies { offlineImplementation(project(':probe')) offlineImplementation(project(':core')) offlineImplementation('com.github.VolmitSoftware.VolmLib:native-common:master-SNAPSHOT') { transitive = false } offlineImplementation(volmLibShared) { transitive = false } } sourceSets.test.compileClasspath += sourceSets.offline.output sourceSets.test.runtimeClasspath += sourceSets.offline.output TaskProvider offlineJar = tasks.register('offlineJar', Jar) { dependsOn(offlineClasses) archiveClassifier = 'offline' from(sourceSets.offline.runtimeClasspath.filter { File file -> file.isDirectory() }) } FileCollection offlineLibraries = sourceSets.offline.runtimeClasspath.filter { File file -> file.isFile() } TaskProvider offlineStartScripts = tasks.register('offlineStartScripts', CreateStartScripts) { dependsOn(offlineJar) mainClass = 'art.arcane.iris.probe.OfflineRegionGenerator' applicationName = 'iris-offline' outputDir = layout.buildDirectory.dir('offline-scripts').get().asFile classpath = files(offlineJar) + offlineLibraries defaultJvmOpts = ['-Xmx8G', '--add-modules=jdk.incubator.vector', '-Djava.awt.headless=true'] } tasks.register('installOffline', Sync) { group = 'distribution' description = 'Installs the standalone native region generator and its runtime libraries.' dependsOn(offlineJar, offlineStartScripts) into(layout.buildDirectory.dir('install/iris-offline')) into('lib') { from(offlineJar, offlineLibraries) } into('bin') { from(offlineStartScripts) filePermissions { unix('rwxr-xr-x') } } } tasks.register('regionMantleInspection', JavaExec) { group = 'verification' dependsOn(testClasses) mainClass = 'art.arcane.iris.probe.HeadlessMantleInspection' classpath = sourceSets.test.runtimeClasspath maxHeapSize = '4G' jvmArgs('--add-modules', 'jdk.incubator.vector', '-Djava.awt.headless=true') doFirst { args(['probePack', 'probeDimension', 'probeSeed', 'probeWorld', 'probeRegionX', 'probeRegionZ'] .collect { String name -> providers.gradleProperty(name).get() }) } } tasks.register('generateOfflineRegions', JavaExec) { group = 'verification' description = 'Writes fresh native TERRAIN checkpoints with exact prerequisites for subsequent native FULL completion.' dependsOn(offlineClasses) mainClass = 'art.arcane.iris.probe.OfflineRegionGenerator' classpath = sourceSets.offline.runtimeClasspath maxHeapSize = '8G' jvmArgs('--add-modules', 'jdk.incubator.vector', '-Djava.awt.headless=true') doFirst { List names = ['probePack', 'probeDimension', 'probeSeed', 'probeChunkX', 'probeChunkZ', 'probeWidth', 'probeRegionsX', 'probeRegionsZ', 'probeParallelism', 'probeSpigot', 'probeWorldName', 'probeLevelKey', 'probeNoiseSettings', 'probeOutput'] args(names.collect { String name -> providers.gradleProperty(name).get() }) } } } project(':adapters:bukkit:nms:v26_3_R1') { Provider fixtureResources = layout.buildDirectory.dir('generated/region-native-fixture') TaskProvider fixtureDescriptor = tasks.register('regionNativeFixtureDescriptor') { outputs.dir(fixtureResources) doLast { File descriptor = fixtureResources.get().file('plugin.yml').asFile descriptor.parentFile.mkdirs() descriptor.text = '''name: RegionNativeFixture version: 1.0 main: art.arcane.iris.probe.RegionNativeFixture api-version: '26.3' depend: [Iris] commands: mcaterrain: description: Export native terrain checkpoints on an isolated test server mcaload: description: Verify native terrain checkpoints finish generation on reload ''' } } TaskProvider compileRegionNativeFixture = tasks.register('compileRegionNativeFixture', JavaCompile) { source(fileTree('src/test/java') { include('art/arcane/iris/probe/RegionNativeFixture.java', 'art/arcane/iris/probe/DetachedNativeTerrain.java') }) source(fileTree('src/offline/java') { include('art/arcane/iris/probe/RegionGenerationWindow.java', 'art/arcane/iris/probe/NativeRegionTerrainWriter.java', 'art/arcane/iris/probe/NativeRegionPlan.java') }) classpath = sourceSets.test.compileClasspath destinationDirectory = layout.buildDirectory.dir('classes/region-native-fixture') javaCompiler = javaToolchains.compilerFor { languageVersion = JavaLanguageVersion.of(25) } options.release = 25 options.compilerArgs.add('-parameters') } tasks.register('regionNativeFixtureJar', Jar) { dependsOn(compileRegionNativeFixture, fixtureDescriptor) archiveFileName = 'mca-native-fixture.jar' from(compileRegionNativeFixture.flatMap { JavaCompile task -> task.destinationDirectory }) from(fixtureResources) } } tasks.withType(PackedJar).configureEach { nativeManifestPath.set(NativeRuntimeArtifacts.MANIFEST) nativeResourceDirectory.set(NativeRuntimeArtifacts.RESOURCES) dependsOn(tasks.named('verifyBukkitArtifact'), nativeRuntime) nativeArtifacts.set(providers.provider { embeddedNatives() }) doLast { PackedJar task -> NativeRuntimeArtifacts.verifyPacked(task.outputJar.get().asFile, nativeRuntimeModules, embeddedNatives()) } }