@@ -186,6 +186,16 @@ minecraft {
186186 // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
187187 args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
188188 }
189+
190+ ['Fresh', 'Reload'].each { String phase ->
191+ create("surfaceIntegration${phase}") {
192+ parent runs.server
193+ workingDirectory layout.buildDirectory.dir('surface-integration-run').get().asFile
194+ property 'forge.logging.console.level', 'info'
195+ property 'surfaceprobe.integrationPhase', phase.toLowerCase(Locale.ROOT)
196+ args '--nogui'
197+ }
198+ }
189199 }
190200}
191201
@@ -291,6 +301,84 @@ tasks.named('test', Test).configure {
291301 useJUnitPlatform()
292302}
293303
304+ def surfaceIntegrationClasses = layout.buildDirectory.dir('surface-integration-fixture/classes')
305+ def compileSurfaceIntegrationTestMod = tasks.register('compileSurfaceIntegrationTestMod', JavaCompile) {
306+ dependsOn tasks.named('classes')
307+ source fileTree('src/biomeIntegrationTest/java')
308+ classpath = files(sourceSets.main.output, sourceSets.main.compileClasspath)
309+ destinationDirectory.set(surfaceIntegrationClasses)
310+ javaCompiler.set(javaToolchains.compilerFor {
311+ languageVersion = JavaLanguageVersion.of(17)
312+ })
313+ options.release = 17
314+ options.encoding = 'UTF-8'
315+ }
316+
317+ def surfaceIntegrationTestModJar = tasks.register('surfaceIntegrationTestModJar', Jar) {
318+ dependsOn compileSurfaceIntegrationTestMod
319+ archiveFileName = 'surfaceprobe.jar'
320+ destinationDirectory = layout.buildDirectory.dir('surface-integration-fixture')
321+ from surfaceIntegrationClasses
322+ from 'src/biomeIntegrationTest/resources'
323+ }
324+
325+ def surfaceIntegrationRunDirectory = layout.buildDirectory.dir('surface-integration-run')
326+ def prepareSurfaceIntegrationTest = tasks.register('prepareSurfaceIntegrationTest') {
327+ dependsOn surfaceIntegrationTestModJar
328+ doLast {
329+ File runDirectory = surfaceIntegrationRunDirectory.get().asFile
330+ delete runDirectory
331+ runDirectory.mkdirs()
332+ copy {
333+ from surfaceIntegrationTestModJar.flatMap { it.archiveFile }
334+ into surfaceIntegrationRunDirectory.map { it.dir('mods') }
335+ }
336+ new File(runDirectory, 'server.properties').setText('''\
337+ level-name=surface-integration-world
338+ level-seed=0
339+ level-type=minecraft:normal
340+ online-mode=false
341+ allow-nether=true
342+ generate-structures=false
343+ spawn-protection=0
344+ max-tick-time=-1
345+ ''', 'UTF-8')
346+ new File(runDirectory, 'eula.txt').setText('eula=true\n', 'UTF-8')
347+ }
348+ }
349+
350+ tasks.configureEach {
351+ if (name == 'runSurfaceIntegrationFresh') {
352+ dependsOn prepareSurfaceIntegrationTest
353+ } else if (name == 'runSurfaceIntegrationReload') {
354+ dependsOn 'runSurfaceIntegrationFresh'
355+ }
356+ }
357+
358+ def surfaceIntegrationTest = tasks.register('surfaceIntegrationTest') {
359+ group = 'verification'
360+ description = 'Verifies provider surfaces and dynamic-biome geology across fresh and reloaded normal terrain.'
361+ dependsOn 'runSurfaceIntegrationReload'
362+ doLast {
363+ File marker = surfaceIntegrationRunDirectory.get().file(
364+ 'surface-integration-world/surfaceprobe-integration.properties').asFile
365+ if (!marker.isFile()) {
366+ throw new GradleException("Surface integration completion marker is missing: ${marker}")
367+ }
368+ Properties result = new Properties()
369+ marker.withInputStream { result.load(it) }
370+ if (result.getProperty('reload_verified') != 'true') {
371+ throw new GradleException("Surface integration reload was not verified: ${marker}")
372+ }
373+ logger.lifecycle('Provider surfaces and dynamic-biome geology verified: {} dimensions, {} columns each, fresh + reload',
374+ result.getProperty('dimensions'), result.getProperty('columns_per_dimension'))
375+ }
376+ }
377+
378+ tasks.named('check') {
379+ dependsOn surfaceIntegrationTest
380+ }
381+
294382// Keep every Eclipse launch input on one physical Gradle cache. Mixing Buildship's
295383// cache with a command-line cache duplicates named Java modules such as FML and Mixin.
296384def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
@@ -463,6 +551,7 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
463551 }
464552
465553 int changedLaunches = 0
554+ int changedTestExclusions = 0
466555 if (eclipseLaunchDir.isDirectory()) {
467556 File eclipseClasses = file('bin/main').canonicalFile
468557 String modClasses = "${mod_id}%%${eclipseClasses.absolutePath}"
@@ -480,6 +569,27 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
480569 /<mapEntry key="MOD_CLASSES" value="[^"]*"\/>/) {
481570 "<mapEntry key=\"MOD_CLASSES\" value=\"${modClasses}\"/>"
482571 }
572+ String excludeTestKey = 'org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE'
573+ String excludeTestAttribute =
574+ "<booleanAttribute key=\"${excludeTestKey}\" value=\"true\"/>"
575+ String beforeTestExclusion = synced
576+ if (synced.contains("key=\"${excludeTestKey}\"")) {
577+ synced = synced.replaceFirst(
578+ /<booleanAttribute key="org\.eclipse\.jdt\.launching\.ATTR_EXCLUDE_TEST_CODE" value="[^"]*"\/>/,
579+ excludeTestAttribute)
580+ } else {
581+ int launchHeaderEnd = synced.indexOf('\n', synced.indexOf('<launchConfiguration'))
582+ if (launchHeaderEnd < 0) {
583+ throw new GradleException("Malformed Eclipse Java launch configuration: ${launchFile}")
584+ }
585+ String lineSeparator = synced.contains('\r\n') ? '\r\n' : '\n'
586+ synced = "${synced.substring(0, launchHeaderEnd + 1)}" +
587+ " ${excludeTestAttribute}${lineSeparator}" +
588+ synced.substring(launchHeaderEnd + 1)
589+ }
590+ if (beforeTestExclusion != synced) {
591+ changedTestExclusions++
592+ }
483593 if (original != synced) {
484594 launchFile.setText(synced, 'UTF-8')
485595 changedLaunches++
@@ -505,7 +615,7 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
505615 changedLaunchGroups++
506616 }
507617 }
508- logger.lifecycle("Eclipse runtime paths aligned with ${eclipseCache} (${stableClasspaths.size()} Forge classpaths, ${changedProjectClasspath} project classpath, ${changedResourceExclusions} metadata exclusion, ${changedPrepareLaunches} prepare launches, ${changedLaunches} slim launches, ${changedLaunchGroups} direct project launches updated)")
618+ logger.lifecycle("Eclipse runtime paths aligned with ${eclipseCache} (${stableClasspaths.size()} Forge classpaths, ${changedProjectClasspath} project classpath, ${changedResourceExclusions} metadata exclusion, ${changedPrepareLaunches} prepare launches, ${changedLaunches} slim launches, ${changedTestExclusions} test exclusions, ${ changedLaunchGroups} direct project launches updated)")
509619 }
510620}
511621
0 commit comments