plugins { id 'application' } group = 'art.arcane' version = rootProject.version application { mainClass = 'art.arcane.iris.probe.ClassloadProbe' } String volmLibCoordinate = providers.gradleProperty('volmLibCoordinate') .orElse('com.github.VolmitSoftware:VolmLib:master-SNAPSHOT') .get() configurations { studioProbeApi } dependencies { implementation(project(':core')) compileOnly(libs.spigot) testImplementation('junit:junit:4.13.2') testImplementation(libs.gson) testImplementation(testFixtures(project(':core'))) testImplementation(volmLibCoordinate) { transitive = false } compileOnly(volmLibCoordinate) { transitive = false } runtimeOnly(libs.paralithic) runtimeOnly(libs.gson) runtimeOnly(libs.lru) runtimeOnly(libs.commons.io) runtimeOnly(libs.commons.lang3) runtimeOnly(libs.fastutil) runtimeOnly(libs.caffeine) runtimeOnly(libs.lz4) runtimeOnly(libs.zip) runtimeOnly(libs.guava) runtimeOnly(libs.oshi) runtimeOnly(libs.byteBuddy.core) runtimeOnly(libs.byteBuddy.agent) studioProbeApi(libs.spigot) { transitive = false } } tasks.named('run', JavaExec).configure { args(project(':core').layout.buildDirectory.dir('classes/java/main').get().asFile.absolutePath) jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(':core:compileJava') } tasks.named('test').configure { dependsOn(':core:compileJava') } tasks.register('hydrologyProbe', JavaExec) { group = 'verification' description = 'Scans deterministic hydrology seeds and reports accepted feature coordinates plus cold and warm planner timings.' mainClass = 'art.arcane.iris.probe.HydrologyPlannerProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(':core:compileJava') } Provider probePack = providers.gradleProperty('probePack') Provider probeDimension = providers.gradleProperty('probeDimension') Provider probeWarmupChunks = providers.gradleProperty('probeWarmupChunks').orElse('256') Provider probeMeasuredChunks = providers.gradleProperty('probeMeasuredChunks').orElse('1024') Provider probeCenterChunkX = providers.gradleProperty('probeCenterChunkX').orElse('2048') Provider probeCenterChunkZ = providers.gradleProperty('probeCenterChunkZ').orElse('2048') Provider probeMulticore = providers.gradleProperty('probeMulticore').orElse('false') Provider probeStudio = providers.gradleProperty('probeStudio').orElse('false') Provider explicitProbeMulticore = providers.gradleProperty('probeMulticore') Provider explicitProbeStudio = providers.gradleProperty('probeStudio') Provider probeSeeds = providers.gradleProperty('probeSeeds') Provider probeMinimumTileX = providers.gradleProperty('probeMinimumTileX') Provider probeMaximumTileX = providers.gradleProperty('probeMaximumTileX') Provider probeMinimumTileZ = providers.gradleProperty('probeMinimumTileZ') Provider probeMaximumTileZ = providers.gradleProperty('probeMaximumTileZ') Provider probeRequiredCoverage = providers.gradleProperty('probeRequiredCoverage') Provider probeSeed = providers.gradleProperty('probeSeed') Provider probeMinimumChunkX = providers.gradleProperty('probeMinimumChunkX') Provider probeMaximumChunkX = providers.gradleProperty('probeMaximumChunkX') Provider probeMinimumChunkZ = providers.gradleProperty('probeMinimumChunkZ') Provider probeMaximumChunkZ = providers.gradleProperty('probeMaximumChunkZ') Provider probeParallelism = providers.gradleProperty('probeParallelism') Provider probeShuffleSeed = providers.gradleProperty('probeShuffleSeed') Provider probeJfr = providers.gradleProperty('probeJfr') Provider probeTileX = providers.gradleProperty('probeTileX') Provider probeTileZ = providers.gradleProperty('probeTileZ') Provider probeOutput = providers.gradleProperty('probeOutput') Provider probeStrictGeometry = providers.gradleProperty('probeStrictGeometry').orElse('false') tasks.register('hydrologyBlockProbe', JavaExec) { group = 'verification' description = 'Generates up to 64 real pack chunks and checks final cane support, channel fluid and mouth ocean connectivity, with block category images.' mainClass = 'art.arcane.iris.probe.HydrologyBlockProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector', '-Djava.awt.headless=true') dependsOn(':core:compileJava') doFirst { Map> required = [ probePack: probePack, probeDimension: probeDimension, probeSeed: probeSeed, probeMinimumChunkX: probeMinimumChunkX, probeMaximumChunkX: probeMaximumChunkX, probeMinimumChunkZ: probeMinimumChunkZ, probeMaximumChunkZ: probeMaximumChunkZ, probeRequiredCoverage: probeRequiredCoverage, probeOutput: probeOutput ] required.each { String name, Provider value -> if (!value.isPresent() || value.get().isBlank()) { throw new GradleException("hydrologyBlockProbe requires -P${name}=") } } args(probePack.get(), probeDimension.get(), probeSeed.get(), probeMinimumChunkX.get(), probeMaximumChunkX.get(), probeMinimumChunkZ.get(), probeMaximumChunkZ.get(), probeRequiredCoverage.get(), probeOutput.get(), probeStudio.get()) } } tasks.register('terrain3DProbe', JavaExec) { group = 'verification' description = 'Generates real pack chunks, verifies volumetric terrain spans and required biome overhang coverage, and exports actual block cross-sections.' mainClass = 'art.arcane.iris.probe.Terrain3DProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector', '-Djava.awt.headless=true') dependsOn(':core:compileJava') doFirst { Map> required = [ probePack: probePack, probeDimension: probeDimension, probeSeed: probeSeed, probeMinimumChunkX: probeMinimumChunkX, probeMaximumChunkX: probeMaximumChunkX, probeMinimumChunkZ: probeMinimumChunkZ, probeMaximumChunkZ: probeMaximumChunkZ, probeRequiredCoverage: probeRequiredCoverage, probeOutput: probeOutput ] required.each { String name, Provider value -> if (!value.isPresent() || value.get().isBlank()) { throw new GradleException("terrain3DProbe requires -P${name}=") } } args(probePack.get(), probeDimension.get(), probeSeed.get(), probeMinimumChunkX.get(), probeMaximumChunkX.get(), probeMinimumChunkZ.get(), probeMaximumChunkZ.get(), probeRequiredCoverage.get(), probeOutput.get(), probeStrictGeometry.get(), probeStudio.get()) } } tasks.register('genProbe', JavaExec) { group = 'verification' description = 'Constructs a real Iris engine over a real pack and generates chunks into buffers on a Bukkit-free JVM.' mainClass = 'art.arcane.iris.probe.GenerationProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(':core:compileJava') doFirst { if (!probePack.isPresent() || probePack.get().isBlank()) { throw new GradleException('genProbe requires -PprobePack=/absolute/path/to/pack') } if (!probeDimension.isPresent() || probeDimension.get().isBlank()) { throw new GradleException('genProbe requires -PprobeDimension=') } args( probePack.get(), probeDimension.get(), probeWarmupChunks.get(), probeMeasuredChunks.get(), probeCenterChunkX.get(), probeCenterChunkZ.get(), probeMulticore.get(), probeStudio.get()) } } tasks.register('hydrologyPackProbe', JavaExec) { group = 'verification' description = 'Scans explicitly bounded real-pack hydrology tiles across multiple engine seeds and enforces accepted feature/profile coverage.' mainClass = 'art.arcane.iris.probe.HydrologyPackProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(':core:compileJava') doFirst { Map> required = [ probePack: probePack, probeDimension: probeDimension, probeSeeds: probeSeeds, probeMinimumTileX: probeMinimumTileX, probeMaximumTileX: probeMaximumTileX, probeMinimumTileZ: probeMinimumTileZ, probeMaximumTileZ: probeMaximumTileZ, probeRequiredCoverage: probeRequiredCoverage, probeStudio: explicitProbeStudio ] required.each { String name, Provider value -> if (!value.isPresent() || value.get().isBlank()) { throw new GradleException("hydrologyPackProbe requires -P${name}=") } } args( probePack.get(), probeDimension.get(), probeSeeds.get(), probeMinimumTileX.get(), probeMaximumTileX.get(), probeMinimumTileZ.get(), probeMaximumTileZ.get(), probeRequiredCoverage.get(), explicitProbeStudio.get()) } } tasks.register('generationOrderProbe', JavaExec) { group = 'verification' description = 'Compares complete real-pack chunk block and biome hashes across forward, reverse, shuffled and bounded-parallel generation orders.' mainClass = 'art.arcane.iris.probe.GenerationOrderProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector') dependsOn(':core:compileJava') doFirst { Map> required = [ probePack: probePack, probeDimension: probeDimension, probeSeed: probeSeed, probeMinimumChunkX: probeMinimumChunkX, probeMaximumChunkX: probeMaximumChunkX, probeMinimumChunkZ: probeMinimumChunkZ, probeMaximumChunkZ: probeMaximumChunkZ, probeParallelism: probeParallelism, probeShuffleSeed: probeShuffleSeed, probeMulticore: explicitProbeMulticore, probeStudio: explicitProbeStudio ] required.each { String name, Provider value -> if (!value.isPresent() || value.get().isBlank()) { throw new GradleException("generationOrderProbe requires -P${name}=") } } args( probePack.get(), probeDimension.get(), probeSeed.get(), probeMinimumChunkX.get(), probeMaximumChunkX.get(), probeMinimumChunkZ.get(), probeMaximumChunkZ.get(), probeParallelism.get(), probeShuffleSeed.get(), explicitProbeMulticore.get(), explicitProbeStudio.get()) } } tasks.register('riverTransectProbe', JavaExec) { group = 'verification' description = 'Plans one hydrology tile over a real pack and renders every surface river as a plan, cross-sections and a summary with ocean-write and containment gates.' mainClass = 'art.arcane.iris.probe.RiverTransectProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector', '-Djava.awt.headless=true') dependsOn(':core:compileJava') doFirst { Map> required = [ probePack: probePack, probeDimension: probeDimension, probeSeed: probeSeed, probeTileX: probeTileX, probeTileZ: probeTileZ, probeOutput: probeOutput ] required.each { String name, Provider value -> if (!value.isPresent() || value.get().isBlank()) { throw new GradleException("riverTransectProbe requires -P${name}=") } } args( probePack.get(), probeDimension.get(), probeSeed.get(), probeTileX.get(), probeTileZ.get(), probeOutput.get(), probeStudio.get()) } } ['hydrologyProbe', 'genProbe', 'hydrologyPackProbe', 'generationOrderProbe', 'riverTransectProbe', 'terrain3DProbe', 'hydrologyBlockProbe'].each { String taskName -> tasks.named(taskName, JavaExec).configure { JavaExec task -> classpath += configurations.studioProbeApi doFirst { if (probeJfr.isPresent()) { String requestedPath = probeJfr.get() if (requestedPath.isBlank()) { throw new GradleException('probeJfr must be a nonblank absolute path') } File recording = new File(requestedPath) if (!recording.isAbsolute()) { throw new GradleException('probeJfr must be an absolute path') } if (recording.isDirectory()) { throw new GradleException('probeJfr must name a recording file, not a directory') } java.nio.file.Path normalized = recording.canonicalFile.toPath() java.nio.file.Path repository = rootProject.projectDir.canonicalFile.toPath() if (normalized.startsWith(repository)) { throw new GradleException('probeJfr must point outside the repository') } File parent = normalized.toFile().parentFile if (parent == null || !parent.isDirectory()) { throw new GradleException('probeJfr parent directory must already exist') } task.jvmArgs( '-XX:FlightRecorderOptions=stackdepth=256', "-XX:StartFlightRecording=filename=${normalized},settings=profile,dumponexit=true" ) } } } } String deserializationPack = providers.gradleProperty('deserializationPack') .orElse(project.file('src/main/resources/deserialization-pack').absolutePath) .get() tasks.register('deserializationProbe', JavaExec) { group = 'verification' description = 'Deserializes entity, spawner and loot pack content through the real Iris Gson loaders on a Bukkit-free JVM to keep Bukkit-typed pack-model fields dead.' mainClass = 'art.arcane.iris.probe.DeserializationProbe' classpath = sourceSets.main.runtimeClasspath jvmArgs('--add-modules', 'jdk.incubator.vector') args(deserializationPack) dependsOn(':core:compileJava') }